lib/curl: make private and update init of HeaderMapIterator
[nit.git] / lib / curl / curl.nit
index 1c1f4cc..8c4ae80 100644 (file)
 # Network functionnalities based on Curl_c module.
 module curl
 
-import curl_c
+import native_curl
 
 # Top level of Curl
 class Curl
-       protected var prim_curl: CCurl
 
        init
        do
-               self.prim_curl = new CCurl.easy_init
                assert curlInstance:self.prim_curl.is_init else
                        print "Curl must be instancied to be used"
                end
        end
+       protected var native = new NativeCurl.easy_init
 
        # Check for correct initialization
-       fun is_ok: Bool do return self.prim_curl.is_init
+       fun is_ok: Bool do return self.native.is_init
 
        # Release Curl instance
-       fun destroy do self.prim_curl.easy_clean
+       fun destroy do self.native.easy_clean
 end
 
 # CURL Request
 class CurlRequest
 
-       var verbose: Bool writable = false
+       var verbose: Bool = false is writable
        private var curl: nullable Curl = null
 
        # Launch request method
        fun execute: CurlResponse is abstract
 
        # Intern perform method, lowest level of request launching
-       private fun perform: nullable CurlResponse
+       private fun perform: nullable CurlResponseFailed
        do
                if not self.curl.is_ok then return answer_failure(0, "Curl instance is not correctly initialized")
 
                var err
 
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.verbose, self.verbose)
+               err = self.curl.native.easy_setopt(new CURLOption.verbose, self.verbose)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
-               err = self.curl.prim_curl.easy_perform
+               err = self.curl.native.easy_perform
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
                return null
        end
 
        # Intern method with return a failed answer with given code and message
-       private fun answer_failure(error_code: Int, error_msg: String): CurlResponse
+       private fun answer_failure(error_code: Int, error_msg: String): CurlResponseFailed
        do
                return new CurlResponseFailed(error_code, error_msg)
        end
@@ -73,15 +72,20 @@ end
 # CURL HTTP Request
 class CurlHTTPRequest
        super CurlRequest
-       super CCurlCallbacks
-       super CurlCallbacksRegisterIntern
+       super NativeCurlCallbacks
 
        var url: String
-       var datas: nullable HeaderMap writable = null
-       var headers: nullable HeaderMap writable = null
+       var datas: nullable HeaderMap = null is writable
+       var headers: nullable HeaderMap = null is writable
+       var delegate: nullable CurlCallbacks = null is writable
 
-       init (url: String, curl: nullable Curl)
+       # Set the user agent for all following HTTP requests
+       fun user_agent=(name: String)
        do
+               curl.native.easy_setopt(new CURLOption.user_agent, name)
+       end
+
+       init (url: String, curl: nullable Curl) is old_style_init do
                self.url = url
                self.curl = curl
        end
@@ -97,37 +101,37 @@ class CurlHTTPRequest
 
                var err
 
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.follow_location, 1)
+               err = self.curl.native.easy_setopt(new CURLOption.follow_location, 1)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.url, url)
+               err = self.curl.native.easy_setopt(new CURLOption.url, url)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
                # Callbacks
-               err = self.curl.prim_curl.register_callback(callback_receiver, new CURLCallbackType.header)
+               err = self.curl.native.register_callback_header(callback_receiver)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
-               err = self.curl.prim_curl.register_callback(callback_receiver, new CURLCallbackType.body)
+               err = self.curl.native.register_callback_body(callback_receiver)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
                # HTTP Header
                if self.headers != null then
                        var headers_joined = self.headers.join_pairs(": ")
-                       err = self.curl.prim_curl.easy_setopt(new CURLOption.httpheader, headers_joined.to_curlslist)
+                       err = self.curl.native.easy_setopt(new CURLOption.httpheader, headers_joined.to_curlslist)
                        if not err.is_ok then return answer_failure(err.to_i, err.to_s)
                end
 
                # Datas
                if self.datas != null then
-                       var postdatas = self.datas.to_url_encoded(self.curl.prim_curl)
-                       err = self.curl.prim_curl.easy_setopt(new CURLOption.postfields, postdatas)
+                       var postdatas = self.datas.to_url_encoded(self.curl.native)
+                       err = self.curl.native.easy_setopt(new CURLOption.postfields, postdatas)
                        if not err.is_ok then return answer_failure(err.to_i, err.to_s)
                end
 
                var err_resp = perform
                if err_resp != null then return err_resp
 
-               var st_code = self.curl.prim_curl.easy_getinfo_long(new CURLInfoLong.response_code)
+               var st_code = self.curl.native.easy_getinfo_long(new CURLInfoLong.response_code)
                if not st_code == null then success_response.status_code = st_code.response
 
                return success_response
@@ -143,16 +147,16 @@ class CurlHTTPRequest
 
                var err
 
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.follow_location, 1)
+               err = self.curl.native.easy_setopt(new CURLOption.follow_location, 1)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.url, url)
+               err = self.curl.native.easy_setopt(new CURLOption.url, url)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
-               err = self.curl.prim_curl.register_callback(callback_receiver, new CURLCallbackType.header)
+               err = self.curl.native.register_callback_header(callback_receiver)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
-               err = self.curl.prim_curl.register_callback(callback_receiver, new CURLCallbackType.stream)
+               err = self.curl.native.register_callback_stream(callback_receiver)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
                var opt_name
@@ -164,28 +168,27 @@ class CurlHTTPRequest
                        return answer_failure(0, "Unable to extract file name, please specify one")
                end
 
-               success_response.i_file = new OFile.open(opt_name.to_cstring)
-               if not success_response.i_file.is_valid then
-                       success_response.i_file.close
+               success_response.file = new FileWriter.open(opt_name)
+               if not success_response.file.is_writable then
                        return answer_failure(0, "Unable to create associated file")
                end
 
                var err_resp = perform
                if err_resp != null then return err_resp
 
-               var st_code = self.curl.prim_curl.easy_getinfo_long(new CURLInfoLong.response_code)
+               var st_code = self.curl.native.easy_getinfo_long(new CURLInfoLong.response_code)
                if not st_code == null then success_response.status_code = st_code.response
 
-               var speed = self.curl.prim_curl.easy_getinfo_double(new CURLInfoDouble.speed_download)
+               var speed = self.curl.native.easy_getinfo_double(new CURLInfoDouble.speed_download)
                if not speed == null then success_response.speed_download = speed.response
 
-               var size = self.curl.prim_curl.easy_getinfo_double(new CURLInfoDouble.size_download)
+               var size = self.curl.native.easy_getinfo_double(new CURLInfoDouble.size_download)
                if not size == null then success_response.size_download = size.response
 
-               var time = self.curl.prim_curl.easy_getinfo_double(new CURLInfoDouble.total_time)
+               var time = self.curl.native.easy_getinfo_double(new CURLInfoDouble.total_time)
                if not time == null then success_response.total_time = time.response
 
-               success_response.i_file.close
+               success_response.file.close
 
                return success_response
        end
@@ -194,20 +197,19 @@ end
 # CURL Mail Request
 class CurlMailRequest
        super CurlRequest
-       super CCurlCallbacks
-
-       var headers: nullable HeaderMap writable = null
-       var headers_body: nullable HeaderMap writable = null
-       var from: nullable String writable = null
-       var to: nullable Array[String] writable = null
-       var cc: nullable Array[String] writable = null
-       var bcc: nullable Array[String] writable = null
-       var subject: nullable String writable = ""
-       var body: nullable String writable = ""
+       super NativeCurlCallbacks
+
+       var headers: nullable HeaderMap = null is writable
+       var headers_body: nullable HeaderMap = null is writable
+       var from: nullable String = null is writable
+       var to: nullable Array[String] = null is writable
+       var cc: nullable Array[String] = null is writable
+       var bcc: nullable Array[String] = null is writable
+       var subject: nullable String = "" is writable
+       var body: nullable String = "" is writable
        private var supported_outgoing_protocol: Array[String] = ["smtp", "smtps"]
 
-       init (curl: nullable Curl)
-       do
+       init (curl: nullable Curl) is old_style_init do
                self.curl = curl
        end
 
@@ -237,7 +239,7 @@ class CurlMailRequest
        end
 
        # Configure server host and user credentials if needed.
-       fun set_outgoing_server(host: String, user: nullable String, pwd: nullable String):nullable CurlResponse
+       fun set_outgoing_server(host: String, user: nullable String, pwd: nullable String): nullable CurlResponseFailed
        do
                # Check Curl initialisation
                if not self.curl.is_ok then return answer_failure(0, "Curl instance is not correctly initialized")
@@ -247,14 +249,14 @@ class CurlMailRequest
                # Host & Protocol
                err = is_supported_outgoing_protocol(host)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.url, host)
+               err = self.curl.native.easy_setopt(new CURLOption.url, host)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
                # Credentials
                if not user == null and not pwd == null then
-                       err = self.curl.prim_curl.easy_setopt(new CURLOption.username, user)
+                       err = self.curl.native.easy_setopt(new CURLOption.username, user)
                        if not err.is_ok then return answer_failure(err.to_i, err.to_s)
-                       err = self.curl.prim_curl.easy_setopt(new CURLOption.password, pwd)
+                       err = self.curl.native.easy_setopt(new CURLOption.password, pwd)
                        if not err.is_ok then return answer_failure(err.to_i, err.to_s)
                end
 
@@ -289,16 +291,16 @@ class CurlMailRequest
 
                var err
 
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.follow_location, 1)
+               err = self.curl.native.easy_setopt(new CURLOption.follow_location, 1)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
-               err = self.curl.prim_curl.easy_setopt(new CURLOption.mail_rcpt, g_rec.to_curlslist)
+               err = self.curl.native.easy_setopt(new CURLOption.mail_rcpt, g_rec.to_curlslist)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
                # From
                if not self.from == null then
                        content = add_pair_to_content(content, "From:", self.from)
-                       err = self.curl.prim_curl.easy_setopt(new CURLOption.mail_from, self.from.as(not null))
+                       err = self.curl.native.easy_setopt(new CURLOption.mail_from, self.from.as(not null))
                        if not err.is_ok then return answer_failure(err.to_i, err.to_s)
                end
 
@@ -314,9 +316,11 @@ class CurlMailRequest
                content = add_conventional_space(content)
                content = add_pair_to_content(content, "", self.body)
                content = add_conventional_space(content)
-               err = self.curl.prim_curl.register_callback(self, once new CURLCallbackType.read)
+
+               err = self.curl.native.register_callback_read(self)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
-               err = self.curl.prim_curl.register_read_datas_callback(self, content)
+
+               err = self.curl.native.register_read_datas_callback(self, content)
                if not err.is_ok then return answer_failure(err.to_i, err.to_s)
 
                var err_resp = perform
@@ -328,12 +332,7 @@ end
 
 # Callbacks Interface, allow you to manage in your way the different streams
 interface CurlCallbacks
-       super CCurlCallbacks
-end
-
-# Callbacks attributes
-abstract class CurlCallbacksRegisterIntern
-       var delegate: nullable CurlCallbacks writable = null
+       super NativeCurlCallbacks
 end
 
 # Abstract Curl request response
@@ -346,12 +345,6 @@ class CurlResponseFailed
 
        var error_code: Int
        var error_msg: String
-
-       init (err_code: Int, err_msg: String)
-       do
-               self.error_code = err_code
-               self.error_msg = err_msg
-       end
 end
 
 # Success Abstract Response Success Class
@@ -380,8 +373,7 @@ class CurlResponseSuccess
        var status_code = 0
 
        # Receive body from request due to body callback registering
-       redef fun body_callback(line: String)
-       do
+       redef fun body_callback(line) do
                self.body_str = "{self.body_str}{line}"
        end
 end
@@ -399,12 +391,12 @@ class CurlFileResponseSuccess
        var speed_download = 0
        var size_download = 0
        var total_time = 0
-       private var i_file: nullable OFile = null
+       private var file: nullable FileWriter = null
 
        # Receive bytes stream from request due to stream callback registering
-       redef fun stream_callback(buffer, size, count)
+       redef fun stream_callback(buffer)
        do
-               self.i_file.write(buffer, size, count)
+               file.write buffer
        end
 end
 
@@ -423,13 +415,14 @@ class HeaderMap
                return res
        end
 
+       # Iterate over all the associations in `self`
        fun iterator: MapIterator[String, String] do return new HeaderMapIterator(self)
 
        # Convert Self to a single string used to post http fields
-       fun to_url_encoded(curl: CCurl): String
+       fun to_url_encoded(curl: NativeCurl): String
        do
                assert curlNotInitialized: curl.is_init else
-                       print "to_url_encoded required a valid instance of CCurl Object."
+                       print "to_url_encoded required a valid instance of NativeCurl Object."
                end
                var str = ""
                var length = self.length
@@ -458,11 +451,11 @@ class HeaderMap
        fun is_empty: Bool do return arr.is_empty
 end
 
-class HeaderMapIterator
+private class HeaderMapIterator
        super MapIterator[String, String]
 
-       private var iterator: Iterator[Couple[String, String]]
-       init(map: HeaderMap) do self.iterator = map.arr.iterator
+       var map: HeaderMap
+       var iterator: Iterator[Couple[String, String]] = map.array.iterator is lazy
 
        redef fun is_ok do return self.iterator.is_ok
        redef fun next do self.iterator.next