Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.org>
  3.  * Copyright 2007 James Bursa <bursa@users.sourceforge.net>
  4.  * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
  5.  *
  6.  * This file is part of NetSurf.
  7.  *
  8.  * NetSurf is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; version 2 of the License.
  11.  *
  12.  * NetSurf is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  */
  20.  
  21. /** \file
  22.  * Fetching of data from a URL (implementation).
  23.  *
  24.  * This implementation uses libcurl's 'multi' interface.
  25.  *
  26.  *
  27.  * The CURL handles are cached in the curl_handle_ring. There are at most
  28.  * ::max_cached_fetch_handles in this ring.
  29.  */
  30.  
  31. #include <assert.h>
  32. #include <errno.h>
  33. #include <inttypes.h>
  34. #include <stdbool.h>
  35. #include <string.h>
  36. #include <strings.h>
  37. #include <time.h>
  38. #include <sys/stat.h>
  39.  
  40. #include <libwapcaplet/libwapcaplet.h>
  41.  
  42. #include "utils/config.h"
  43. //#include <openssl/ssl.h>
  44. #include "content/fetch.h"
  45. #include "content/fetchers/curl.h"
  46. #include "content/urldb.h"
  47. #include "desktop/netsurf.h"
  48. #include "desktop/options.h"
  49. #include "utils/log.h"
  50. #include "utils/messages.h"
  51. #include "utils/schedule.h"
  52. #include "utils/utils.h"
  53. #include "utils/ring.h"
  54. #include "utils/useragent.h"
  55.  
  56. /* BIG FAT WARNING: This is here because curl doesn't give you an FD to
  57.  * poll on, until it has processed a bit of the handle.  So we need schedules
  58.  * in order to make this work.
  59.  */
  60. #include <desktop/browser.h>
  61.  
  62. /* uncomment this to use scheduler based calling
  63. #define FETCHER_CURLL_SCHEDULED 1
  64. */
  65.  
  66. typedef int X509_STORE_CTX;
  67. typedef int X509;
  68. #define CURL_ERROR_SIZE 0
  69. typedef int CURLcode;
  70. typedef int curl_infotype;
  71. /** SSL certificate info */
  72. struct cert_info {
  73.         X509 *cert;             /**< Pointer to certificate */
  74.         long err;               /**< OpenSSL error code */
  75. };
  76.  
  77. /** Information for a single fetch. */
  78. struct curl_fetch_info {
  79.         struct fetch *fetch_handle; /**< The fetch handle we're parented by. */
  80.         CURL * curl_handle;     /**< cURL handle if being fetched, or 0. */
  81.         bool had_headers;       /**< Headers have been processed. */
  82.         bool abort;             /**< Abort requested. */
  83.         bool stopped;           /**< Download stopped on purpose. */
  84.         bool only_2xx;          /**< Only HTTP 2xx responses acceptable. */
  85.         bool downgrade_tls;     /**< Downgrade to TLS <= 1.0 */
  86.         nsurl *url;             /**< URL of this fetch. */
  87.         lwc_string *host;       /**< The hostname of this fetch. */
  88.         struct curl_slist *headers;     /**< List of request headers. */
  89.         char *location;         /**< Response Location header, or 0. */
  90.         unsigned long content_length;   /**< Response Content-Length, or 0. */
  91.         char *cookie_string;    /**< Cookie string for this fetch */
  92.         char *realm;            /**< HTTP Auth Realm */
  93.         char *post_urlenc;      /**< Url encoded POST string, or 0. */
  94.         long http_code; /**< HTTP result code from cURL. */
  95.         struct curl_httppost *post_multipart;   /**< Multipart post data, or 0. */
  96. #define MAX_CERTS 10
  97.         struct cert_info cert_data[MAX_CERTS];  /**< HTTPS certificate data */
  98.         unsigned int last_progress_update;      /**< Time of last progress update */
  99. };
  100.  
  101. struct cache_handle {
  102.         CURL *handle; /**< The cached cURL handle */
  103.         lwc_string *host;   /**< The host for which this handle is cached */
  104.  
  105.         struct cache_handle *r_prev; /**< Previous cached handle in ring. */
  106.         struct cache_handle *r_next; /**< Next cached handle in ring. */
  107. };
  108.  
  109. CURLM *fetch_curl_multi;                /**< Global cURL multi handle. */
  110. /** Curl handle with default options set; not used for transfers. */
  111. static CURL *fetch_blank_curl;
  112. static struct cache_handle *curl_handle_ring = 0; /**< Ring of cached handles */
  113. static int curl_fetchers_registered = 0;
  114. static bool curl_with_openssl;
  115.  
  116. static char fetch_error_buffer[CURL_ERROR_SIZE]; /**< Error buffer for cURL. */
  117. static char fetch_proxy_userpwd[100];   /**< Proxy authentication details. */
  118.  
  119. static bool fetch_curl_initialise(lwc_string *scheme);
  120. static void fetch_curl_finalise(lwc_string *scheme);
  121. static bool fetch_curl_can_fetch(const nsurl *url);
  122. static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
  123.                  bool only_2xx, bool downgrade_tls, const char *post_urlenc,
  124.                  const struct fetch_multipart_data *post_multipart,
  125.                  const char **headers);
  126. static bool fetch_curl_start(void *vfetch);
  127. static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
  128.                 CURL *handle);
  129. static CURL *fetch_curl_get_handle(lwc_string *host);
  130. static void fetch_curl_cache_handle(CURL *handle, lwc_string *host);
  131. static CURLcode fetch_curl_set_options(struct curl_fetch_info *f);
  132. static CURLcode fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx,
  133.                                      void *p);
  134. static void fetch_curl_abort(void *vf);
  135. static void fetch_curl_stop(struct curl_fetch_info *f);
  136. static void fetch_curl_free(void *f);
  137. static void fetch_curl_poll(lwc_string *scheme_ignored);
  138. static void fetch_curl_done(CURL *curl_handle, CURLcode result);
  139. static int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
  140.                 double ultotal, double ulnow);
  141. static int fetch_curl_ignore_debug(CURL *handle,
  142.                                    curl_infotype type,
  143.                                    char *data,
  144.                                    size_t size,
  145.                                    void *userptr);
  146. static size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
  147.                               void *_f);
  148. static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
  149.                                 void *_f);
  150. static bool fetch_curl_process_headers(struct curl_fetch_info *f);
  151. static struct curl_httppost *fetch_curl_post_convert(
  152.                 const struct fetch_multipart_data *control);
  153. static int fetch_curl_verify_callback(int preverify_ok,
  154.                 X509_STORE_CTX *x509_ctx);
  155. static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx,
  156.                 void *parm);
  157.  
  158.  
  159. /**
  160.  * Initialise the fetcher.
  161.  *
  162.  * Must be called once before any other function.
  163.  */
  164.  
  165. void fetch_curl_register(void)
  166. {
  167.  
  168. lwc_string *scheme;
  169.  
  170.  
  171. LOG(("curl register\n"));
  172.  
  173. lwc_intern_string("http", SLEN("http"), &scheme);
  174.  
  175.         if (!fetch_add_fetcher(scheme,
  176.                                 fetch_curl_initialise,
  177.                                 fetch_curl_can_fetch,
  178.                                 fetch_curl_setup,
  179.                                 fetch_curl_start,
  180.                                 fetch_curl_abort,
  181.                                 fetch_curl_free,
  182. #ifdef FETCHER_CURLL_SCHEDULED
  183.                                        NULL,
  184. #else
  185.                                 fetch_curl_poll,
  186. #endif
  187.                                 fetch_curl_finalise)) {
  188.                         LOG(("Unable to register cURL fetcher for HTTP"));
  189.                 }
  190.                
  191.                
  192.                 lwc_intern_string("https", SLEN("https"), &scheme);
  193.  
  194.         if (!fetch_add_fetcher(scheme,
  195.                                 fetch_curl_initialise,
  196.                                 fetch_curl_can_fetch,
  197.                                 fetch_curl_setup,
  198.                                 fetch_curl_start,
  199.                                 fetch_curl_abort,
  200.                                 fetch_curl_free,
  201. #ifdef FETCHER_CURLL_SCHEDULED
  202.                                        NULL,
  203. #else
  204.                                 fetch_curl_poll,
  205. #endif
  206.                                 fetch_curl_finalise)) {
  207.                         LOG(("Unable to register cURL fetcher for HTTPS"));
  208.                 }
  209.  
  210. }
  211.  
  212.  
  213. /**
  214.  * Initialise a cURL fetcher.
  215.  */
  216.  
  217. bool fetch_curl_initialise(lwc_string *scheme)
  218. {
  219.  
  220. LOG(("curl initi lwc\n"));
  221.         return true; /* Always succeeds */
  222. }
  223.  
  224.  
  225. /**
  226.  * Finalise a cURL fetcher
  227.  */
  228.  
  229. void fetch_curl_finalise(lwc_string *scheme)
  230. {
  231. LOG(("curl finali\n"));
  232. }
  233.  
  234. bool fetch_curl_can_fetch(const nsurl *url)
  235. {
  236.         LOG(("curl can fetch\n"));
  237.         return false;
  238. }
  239.  
  240. /**
  241.  * Start fetching data for the given URL.
  242.  *
  243.  * The function returns immediately. The fetch may be queued for later
  244.  * processing.
  245.  *
  246.  * A pointer to an opaque struct curl_fetch_info is returned, which can be
  247.  * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory
  248.  * is exhausted (or some other fatal error occurred).
  249.  *
  250.  * The caller must supply a callback function which is called when anything
  251.  * interesting happens. The callback function is first called with msg
  252.  * FETCH_HEADER, with the header in data, then one or more times
  253.  * with FETCH_DATA with some data for the url, and finally with
  254.  * FETCH_FINISHED. Alternatively, FETCH_ERROR indicates an error occurred:
  255.  * data contains an error message. FETCH_REDIRECT may replace the FETCH_HEADER,
  256.  * FETCH_DATA, FETCH_FINISHED sequence if the server sends a replacement URL.
  257.  *
  258.  * Some private data can be passed as the last parameter to fetch_start, and
  259.  * callbacks will contain this.
  260.  */
  261.  
  262. void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
  263.                  bool only_2xx, bool downgrade_tls, const char *post_urlenc,
  264.                  const struct fetch_multipart_data *post_multipart,
  265.                  const char **headers)
  266. {
  267. LOG(("curl setup\n"));
  268.  
  269. return;
  270. }
  271.  
  272.  
  273. /**
  274.  * Dispatch a single job
  275.  */
  276. bool fetch_curl_start(void *vfetch)
  277. {
  278. LOG(("curl start\n"));
  279.         return 0;
  280. }
  281.  
  282.  
  283. /**
  284.  * Initiate a fetch from the queue.
  285.  *
  286.  * Called with a fetch structure and a CURL handle to be used to fetch the
  287.  * content.
  288.  *
  289.  * This will return whether or not the fetch was successfully initiated.
  290.  */
  291.  
  292. bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
  293. {
  294.         LOG(("curl initi fetch\n"));
  295.         return 0;
  296. }
  297.  
  298.  
  299. /**
  300.  * Find a CURL handle to use to dispatch a job
  301.  */
  302.  
  303. CURL *fetch_curl_get_handle(lwc_string *host)
  304. {
  305. LOG(("curl get handle\n"));
  306.         return 0;
  307. }
  308.  
  309.  
  310. /**
  311.  * Cache a CURL handle for the provided host (if wanted)
  312.  */
  313.  
  314. void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
  315. {
  316.         LOG(("curl cache handle\n"));
  317. }
  318.  
  319.  
  320. /**
  321.  * Set options specific for a fetch.
  322.  */
  323.  
  324. typedef int CURLcode;
  325.  
  326. CURLcode
  327. fetch_curl_set_options(struct curl_fetch_info *f)
  328. {
  329.         LOG(("curl set options\n"));
  330.         return -1;
  331. }
  332.  
  333.  
  334. /**
  335.  * cURL SSL setup callback
  336.  */
  337.  
  338. CURLcode
  339. fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
  340. {
  341.         LOG(("curlcodessl\n"));
  342.        
  343.         return -1;
  344. }
  345.  
  346.  
  347. /**
  348.  * Abort a fetch.
  349.  */
  350.  
  351. void fetch_curl_abort(void *vf)
  352. {
  353. LOG(("curl abort\n"));
  354. }
  355.  
  356.  
  357. /**
  358.  * Clean up the provided fetch object and free it.
  359.  *
  360.  * Will prod the queue afterwards to allow pending requests to be initiated.
  361.  */
  362.  
  363. void fetch_curl_stop(struct curl_fetch_info *f)
  364. {
  365.         LOG(("curl stop\n"));
  366. }
  367.  
  368.  
  369. /**
  370.  * Free a fetch structure and associated resources.
  371.  */
  372.  
  373. void fetch_curl_free(void *vf)
  374. {
  375.         LOG(("curl free\n"));
  376. }
  377.  
  378.  
  379. /**
  380.  * Do some work on current fetches.
  381.  *
  382.  * Must be called regularly to make progress on fetches.
  383.  */
  384.  
  385. void fetch_curl_poll(lwc_string *scheme_ignored)
  386. {
  387.         LOG(("curl poll\n"));
  388. }
  389.  
  390.  
  391. /**
  392.  * Handle a completed fetch (CURLMSG_DONE from curl_multi_info_read()).
  393.  *
  394.  * \param  curl_handle  curl easy handle of fetch
  395.  */
  396.  
  397. void fetch_curl_done(CURL *curl_handle, CURLcode result)
  398. {
  399.         LOG(("curl done\n"));
  400. }
  401.  
  402.  
  403. /**
  404.  * Callback function for fetch progress.
  405.  */
  406.  
  407. int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
  408.                         double ultotal, double ulnow)
  409. {
  410.         LOG(("curl progress\n"));
  411.         return 0;
  412. }
  413.  
  414.  
  415.  
  416. /**
  417.  * Ignore everything given to it.
  418.  *
  419.  * Used to ignore cURL debug.
  420.  */
  421.  
  422. int fetch_curl_ignore_debug(CURL *handle,
  423.                             curl_infotype type,
  424.                             char *data,
  425.                             size_t size,
  426.                             void *userptr)
  427. {
  428.         LOG(("curl igdebug\n"));
  429.         return 0;
  430. }
  431.  
  432.  
  433. /**
  434.  * Callback function for cURL.
  435.  */
  436.  
  437. size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
  438.                        void *_f)
  439. {
  440.         LOG(("curl callback\n"));
  441.                 return 0;
  442. }
  443.  
  444.  
  445. /**
  446.  * Callback function for headers.
  447.  *
  448.  * See RFC 2616 4.2.
  449.  */
  450.  
  451. size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
  452.                          void *_f)
  453.                          
  454. {
  455.         LOG(("curl header\n"));
  456.                 return 0;
  457. }
  458.  
  459. /**
  460.  * Find the status code and content type and inform the caller.
  461.  *
  462.  * Return true if the fetch is being aborted.
  463.  */
  464.  
  465. bool fetch_curl_process_headers(struct curl_fetch_info *f)
  466. {
  467. LOG(("curl proc head\n"));
  468.         return false;
  469. }
  470.  
  471.  
  472. /**
  473.  * Convert a list of struct ::fetch_multipart_data to a list of
  474.  * struct curl_httppost for libcurl.
  475.  */
  476. struct curl_httppost *
  477. fetch_curl_post_convert(const struct fetch_multipart_data *control)
  478. {
  479.         struct curl_httppost *post = 0;
  480.        
  481.         LOG(("curl post - FAIL\n"));
  482.         return post;
  483. }
  484.  
  485.  
  486. /**
  487.  * OpenSSL Certificate verification callback
  488.  * Stores certificate details in fetch struct.
  489.  */
  490.  
  491. int fetch_curl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
  492. {
  493.        
  494.         LOG(("curl verify\n"));
  495.         return 0;
  496. }
  497.  
  498.  
  499. /**
  500.  * OpenSSL certificate chain verification callback
  501.  * Verifies certificate chain, setting up context for fetch_curl_verify_callback
  502.  */
  503.  
  504. int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
  505. {
  506.  
  507. LOG(("curl cert verify\n"));
  508.         return 0;
  509. }
  510.