예제 #1
0
파일: http.c 프로젝트: fredollinger/dillo
/*
 * Asynchronously create a new http connection for 'Url'
 * We'll set some socket parameters; the rest will be set later
 * when the IP is known.
 * ( Data1 = Web structure )
 * Return value: 0 on success, -1 otherwise
 */
static int Http_get(ChainLink *Info, void *Data1)
{
   SocketData_t *S;
   char *hostname;

   S = a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey));
   /* Reference Web data */
   S->web = Data1;
   /* Reference Info data */
   S->Info = Info;

   /* Proxy support */
   if (Http_must_use_proxy(S->web->url)) {
      hostname = dStrdup(URL_HOST(HTTP_Proxy));
      S->port = URL_PORT(HTTP_Proxy);
      S->flags |= HTTP_SOCKET_USE_PROXY;
   } else {
      hostname = dStrdup(URL_HOST(S->web->url));
      S->port = URL_PORT(S->web->url);
      S->flags &= ~HTTP_SOCKET_USE_PROXY;
   }

   /* Let the user know what we'll do */
   MSG_BW(S->web, 1, "DNS resolving %s", URL_HOST_(S->web->url));

   /* Let the DNS engine resolve the hostname, and when done,
    * we'll try to connect the socket from the callback function */
   a_Dns_resolve(hostname, Http_dns_cb, Info->LocalKey);

   dFree(hostname);
   return 0;
}
예제 #2
0
파일: http.c 프로젝트: fredollinger/dillo
/*
 * Callback function for the DNS resolver.
 * Continue connecting the socket, or abort upon error condition.
 * S->web is checked to assert the operation wasn't aborted while waiting.
 */
static void Http_dns_cb(int Status, Dlist *addr_list, void *data)
{
   int SKey = VOIDP2INT(data);
   SocketData_t *S;
   HostConnection_t *hc;

   S = a_Klist_get_data(ValidSocks, SKey);
   if (S) {
      if (!a_Web_valid(S->web)) {
         a_Chain_bfcb(OpAbort, S->Info, NULL, "Both");
         dFree(S->Info);
         Http_socket_free(SKey);

      } else if (Status == 0 && addr_list) {
         /* Successful DNS answer; save the IP */
         S->addr_list = addr_list;
         S->flags |= HTTP_SOCKET_QUEUED;
         if (S->flags & HTTP_SOCKET_USE_PROXY)
            hc = Http_host_connection_get(URL_HOST(HTTP_Proxy));
         else
            hc = Http_host_connection_get(URL_HOST(S->web->url));
         Http_socket_enqueue(&hc->queue, S);
         Http_connect_queued_sockets(hc);
      } else {
         /* DNS wasn't able to resolve the hostname */
         MSG_BW(S->web, 0, "ERROR: Dns can't resolve %s",
            (S->flags & HTTP_SOCKET_USE_PROXY) ? URL_HOST_(HTTP_Proxy) :
                                                 URL_HOST_(S->web->url));
         a_Chain_bfcb(OpAbort, S->Info, NULL, "Both");
         dFree(S->Info);
         Http_socket_free(SKey);
      }
   }
}
예제 #3
0
파일: http.c 프로젝트: fredollinger/dillo
/*
 * Test proxy settings and check the no_proxy domains list
 * Return value: whether to use proxy or not.
 */
static int Http_must_use_proxy(const DilloUrl *url)
{
   char *np, *p, *tok;
   int ret = 0;

   if (HTTP_Proxy) {
      ret = 1;
      if (prefs.no_proxy) {
         const char *host = URL_HOST(url);
         size_t host_len = strlen(host);

         np = dStrdup(prefs.no_proxy);
         for (p = np; (tok = dStrsep(&p, " "));  ) {
            int start = host_len - strlen(tok);

            if (start >= 0 && dStrAsciiCasecmp(host + start, tok) == 0) {
               /* no_proxy token is suffix of host string */
               ret = 0;
               break;
            }
         }
         dFree(np);
      }
   }
   _MSG("Http_must_use_proxy: %s\n  %s\n", URL_STR(url), ret ? "YES":"NO");
   return ret;
}
예제 #4
0
파일: auth.c 프로젝트: epitron/dillo
/*
 * Return: Nonzero if we got new credentials from the user and everything
 * seems fine.
 */
static int Auth_do_auth_dialog(const AuthParse_t *auth_parse,
                               const DilloUrl *url)
{
   int ret;
   char *title, *msg;
   AuthDialogData_t *data;
   const char *typestr = auth_parse->type == DIGEST ? "Digest" : "Basic";

   _MSG("auth.c: Auth_do_auth_dialog: realm = '%s'\n", auth_parse->realm);

   title = dStrconcat("Dillo: Password for ", auth_parse->realm, NULL);
   msg = dStrconcat("The server at ", URL_HOST(url), " requires a username"
                    " and password for  \"", auth_parse->realm, "\".\n\n"
                    "Authentication scheme: ", typestr, NULL);
   data = dNew(AuthDialogData_t, 1);
   data->auth_parse = auth_parse;
   data->url = a_Url_dup(url);
   ret = a_Dialog_user_password(title, msg, Auth_do_auth_dialog_cb, data);
   dFree(title); dFree(msg);
   a_Url_free((void *)data->url);
   dFree(data);
   return ret;
}
예제 #5
0
파일: cache.c 프로젝트: fredollinger/dillo
/*
 * Scan, allocate, and set things according to header info.
 * (This function needs the whole header to work)
 */
static void Cache_parse_header(CacheEntry_t *entry)
{
   char *header = entry->Header->str;
   char *Length, *Type, *location_str, *encoding;
#ifndef DISABLE_COOKIES
   Dlist *Cookies;
#endif
   Dlist *warnings;
   void *data;
   int i;

   _MSG("Cache_parse_header\n");

   if (entry->Header->len > 12) {
      if (header[9] == '1' && header[10] == '0' && header[11] == '0') {
         /* 100: Continue. The "real" header has not come yet. */
         MSG("An actual 100 Continue header!\n");
         entry->Flags &= ~CA_GotHeader;
         dStr_free(entry->Header, 1);
         entry->Header = dStr_new("");
         return;
      }
      if (header[9] == '3' && header[10] == '0' &&
          (location_str = Cache_parse_field(header, "Location"))) {
         /* 30x: URL redirection */
         DilloUrl *location_url = a_Url_new(location_str,URL_STR_(entry->Url));

         if (prefs.filter_auto_requests == PREFS_FILTER_SAME_DOMAIN &&
             !a_Url_same_organization(entry->Url, location_url)) {
            /* don't redirect; just show body like usual (if any) */
            MSG("Redirection not followed from %s to %s\n",
                URL_HOST(entry->Url), URL_STR(location_url));
            a_Url_free(location_url);
         } else {
            entry->Flags |= CA_Redirect;
            if (header[11] == '1')
               entry->Flags |= CA_ForceRedirect;  /* 301 Moved Permanently */
            else if (header[11] == '2')
               entry->Flags |= CA_TempRedirect;   /* 302 Temporary Redirect */

            if (URL_FLAGS(location_url) & (URL_Post + URL_Get) &&
                dStrAsciiCasecmp(URL_SCHEME(location_url), "dpi") == 0 &&
                dStrAsciiCasecmp(URL_SCHEME(entry->Url), "dpi") != 0) {
               /* Forbid dpi GET and POST from non dpi-generated urls */
               MSG("Redirection Denied! '%s' -> '%s'\n",
                   URL_STR(entry->Url), URL_STR(location_url));
               a_Url_free(location_url);
            } else {
               entry->Location = location_url;
            }
         }
         dFree(location_str);
      } else if (strncmp(header + 9, "401", 3) == 0) {
         entry->Auth =
            Cache_parse_multiple_fields(header, "WWW-Authenticate");
      } else if (strncmp(header + 9, "404", 3) == 0) {
         entry->Flags |= CA_NotFound;
      }
   }

   if ((warnings = Cache_parse_multiple_fields(header, "Warning"))) {
      for (i = 0; (data = dList_nth_data(warnings, i)); ++i) {
         MSG_HTTP("%s\n", (char *)data);
         dFree(data);
      }
      dList_free(warnings);
   }

   /*
    * Get Transfer-Encoding and initialize decoder
    */
   encoding = Cache_parse_field(header, "Transfer-Encoding");
   entry->TransferDecoder = a_Decode_transfer_init(encoding);


   if ((Length = Cache_parse_field(header, "Content-Length")) != NULL) {
      if (encoding) {
         /*
          * If Transfer-Encoding is present, Content-Length must be ignored.
          * If the Transfer-Encoding is non-identity, it is an error.
          */
         if (dStrAsciiCasecmp(encoding, "identity"))
            MSG_HTTP("Content-Length and non-identity Transfer-Encoding "
                     "headers both present.\n");
      } else {
         entry->Flags |= CA_GotLength;
         entry->ExpectedSize = MAX(strtol(Length, NULL, 10), 0);
      }
      dFree(Length);
   }

   dFree(encoding); /* free Transfer-Encoding */

#ifndef DISABLE_COOKIES
   if ((Cookies = Cache_parse_multiple_fields(header, "Set-Cookie"))) {
      CacheClient_t *client;

      for (i = 0; (client = dList_nth_data(ClientQueue, i)); ++i) {
         if (client->Url == entry->Url) {
            DilloWeb *web = client->Web;

            if (!web->requester ||
                a_Url_same_organization(entry->Url, web->requester)) {
               char *server_date = Cache_parse_field(header, "Date");

               a_Cookies_set(Cookies, entry->Url, server_date);
               dFree(server_date);
               break;
            }
         }
      }
      if (i >= dList_length(ClientQueue)) {
         MSG("Cache: cookies not accepted from '%s'\n", URL_STR(entry->Url));
      }

      for (i = 0; (data = dList_nth_data(Cookies, i)); ++i)
         dFree(data);
      dList_free(Cookies);
   }
#endif /* !DISABLE_COOKIES */

   /*
    * Get Content-Encoding and initialize decoder
    */
   encoding = Cache_parse_field(header, "Content-Encoding");
   entry->ContentDecoder = a_Decode_content_init(encoding);
   dFree(encoding);

   if (entry->ExpectedSize > 0) {
      if (entry->ExpectedSize > HUGE_FILESIZE) {
         entry->Flags |= CA_HugeFile;
      }
      /* Avoid some reallocs. With MAX_INIT_BUF we avoid a SEGFAULT
       * with huge files (e.g. iso files).
       * Note: the buffer grows automatically. */
      dStr_free(entry->Data, 1);
      entry->Data = dStr_sized_new(MIN(entry->ExpectedSize, MAX_INIT_BUF));
   }

   /* Get Content-Type */
   if ((Type = Cache_parse_field(header, "Content-Type"))) {
      /* This HTTP Content-Type is not trusted. It's checked against real data
       * in Cache_process_queue(); only then CA_GotContentType becomes true. */
      a_Cache_set_content_type(entry->Url, Type, "http");
      _MSG("TypeHdr  {%s} {%s}\n", Type, URL_STR(entry->Url));
      _MSG("TypeMeta {%s}\n", entry->TypeMeta);
      dFree(Type);
   }
   Cache_ref_data(entry);
}
예제 #6
0
ret_t
cherokee_request_header_build_string (cherokee_request_header_t *request, cherokee_buffer_t *buf, cherokee_buffer_t *tmp1, cherokee_buffer_t *tmp2)
{
	ret_t           ret;
	const char     *ptr;
	cuint_t         len;
	cherokee_url_t *url = REQUEST_URL(request);

	/* 200 bytes should be enough for a small header
	 */
	cherokee_buffer_ensure_size (buf, 200);

	/* Add main request line:
	 * GET /dir/object HTTP/1.1
	 */
	ret = cherokee_http_method_to_string (request->method, &ptr, &len);
	if (ret != ret_ok) return ret;

	ret = cherokee_buffer_add (buf, ptr, len);
	if (ret != ret_ok) return ret;

	cherokee_buffer_add_str (buf, " ");

	/* Check if the requests goes through a proxy
	 */
	if (request->proxy) {
		cherokee_buffer_add_str (buf, "http://");
		cherokee_buffer_add_buffer (buf, URL_HOST(url));
	}

	cherokee_buffer_add_buffer (buf, URL_REQUEST(url));

	switch (REQUEST_VERSION(request)) {
	case http_version_11:
		cherokee_buffer_add_str (buf, " HTTP/1.1" CRLF);
		break;
	case http_version_10:
		cherokee_buffer_add_str (buf, " HTTP/1.0" CRLF);
		break;
	default:
		SHOULDNT_HAPPEN;
		return ret_error;
	}

	/* Add "Host:" header - in HTTP/1.1
	 */
	if (REQUEST_VERSION(request) == http_version_11) {
		cherokee_buffer_add_str    (buf, "Host: ");
		cherokee_buffer_add_buffer (buf, URL_HOST(url));
		cherokee_buffer_add_str    (buf, CRLF);
	}

	/* Post information
	 */
	if (request->post_len != 0) {
		/* "Content-Length: " FMT_OFFSET CRLF, request->post_len;
		 */
		cherokee_buffer_add_str      (buf, "Content-Length: ");
		cherokee_buffer_add_ullong10 (buf, (cullong_t) request->post_len);
		cherokee_buffer_add_str      (buf, CRLF);
	}

	/* Add "Connection:" header
	 */
	if (REQUEST_KEEPALIVE(request)) {
		cherokee_buffer_add_str (buf, "Connection: Keep-Alive"CRLF);
	} else {
		cherokee_buffer_add_str (buf, "Connection: close"CRLF);
	}

	/* Authentication
	 */
	if (! cherokee_buffer_is_empty (&request->user) ||
	    ! cherokee_buffer_is_empty (&request->password)) {
		cherokee_buffer_clean (tmp1);
		cherokee_buffer_clean (tmp2);

		cherokee_buffer_add_buffer (tmp1, &request->user);
		cherokee_buffer_add_char   (tmp1, ':');
		cherokee_buffer_add_buffer (tmp1, &request->password);

		cherokee_buffer_encode_base64 (tmp1, tmp2);

		cherokee_buffer_add_str    (buf, "Authorization: Basic ");
		cherokee_buffer_add_buffer (buf, tmp2);
		cherokee_buffer_add_str    (buf, CRLF);
	}

	/* Extra headers
	 */
	if (! cherokee_buffer_is_empty (&request->extra_headers)) {
		cherokee_buffer_add_buffer (buf, &request->extra_headers);
	}

	/* Finish the header
	 */
	cherokee_buffer_add_str (buf, CRLF);
	return ret_ok;
}