pike.git / lib / modules / Protocols.pmod / HTTP.pmod / module.pmod

version» Context lines:

pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:39:   constant HTTP_CONFLICT = 409; // RFC 2616 10.4.10: Conflict   constant HTTP_GONE = 410; // RFC 2616 10.4.11: Gone   constant HTTP_LENGTH_REQ = 411; // RFC 2616 10.4.12: Length Required   constant HTTP_PRECOND_FAILED = 412; // RFC 2616 10.4.13: Precondition Failed   constant HTTP_REQ_TOO_LARGE = 413; // RFC 2616 10.4.14: Request Entity Too Large   constant HTTP_URI_TOO_LONG = 414; // RFC 2616 10.4.15: Request-URI Too Long   constant HTTP_UNSUPP_MEDIA = 415; // RFC 2616 10.4.16: Unsupported Media Type   constant HTTP_BAD_RANGE = 416; // RFC 2616 10.4.17: Requested Range Not Satisfiable   constant HTTP_EXPECT_FAILED = 417; // RFC 2616 10.4.18: Expectation Failed   constant HTCPCP_TEAPOT = 418; // RFC 2324 2.3.2: I'm a teapot + constant HTTP_MISDIRECTED_REQ = 421; // RFC 7540 9.1.2: Misdirected Request   constant DAV_UNPROCESSABLE = 422; // RFC 2518 10.3: Unprocessable Entry   constant DAV_LOCKED = 423; // RFC 2518 10.4: Locked   constant DAV_FAILED_DEP = 424; // RFC 2518 10.5: Failed Dependency    -  + constant HTTP_LEGALLY_RESTRICTED= 451; // Draft: Unavailable for Legal Reasons +    // Server errors   constant HTTP_INTERNAL_ERR = 500; // RFC 2616 10.5.1: Internal Server Error   constant HTTP_NOT_IMPL = 501; // RFC 2616 10.5.2: Not Implemented   constant HTTP_BAD_GW = 502; // RFC 2616 10.5.3: Bad Gateway   constant HTTP_UNAVAIL = 503; // RFC 2616 10.5.4: Service Unavailable   constant HTTP_GW_TIMEOUT = 504; // RFC 2616 10.5.5: Gateway Timeout   constant HTTP_UNSUPP_VERSION = 505; // RFC 2616 10.5.6: HTTP Version Not Supported   constant TCN_VARIANT_NEGOTIATES = 506; // RFC 2295 8.1: Variant Also Negotiates   constant DAV_STORAGE_FULL = 507; // RFC 2518 10.6: Insufficient Storage    -  + constant response_codes = + ([ +  // Informational +  100:"100 Continue", +  101:"101 Switching Protocols", +  102:"102 Processing", // WebDAV +  103:"103 Checkpoint", +  122:"122 Request-URI too long", // a non standard IE7 error +  +  // Successful +  200:"200 OK", +  201:"201 Created, URI follows", +  202:"202 Accepted", +  203:"203 Non-Authoritative Information", +  204:"204 No Content", +  205:"205 Reset Content", +  206:"206 Partial Content", // Byte ranges +  207:"207 Multi-Status", // WebDAV +  226:"226 IM Used", // RFC 3229 +  +  // Redirection +  300:"300 Moved", +  301:"301 Permanent Relocation", +  302:"302 Found", // a potential alligator swamp. for HTTP/1.1, use 303/307. +  303:"303 See Other", // temporary redirect, any POST data is received, use GET. +  304:"304 Not Modified", +  305:"305 Use Proxy", +  306:"306 Switch Proxy", // Deprecated +  307:"307 Temporary Redirect", // retry request elsewhere, don't change method. +  308:"308 Resume Incomplete", +  +  // Client Error +  400:"400 Bad Request", +  401:"401 Access denied", +  402:"402 Payment Required", +  403:"403 Forbidden", +  404:"404 No such file or directory.", +  405:"405 Method not allowed", +  406:"406 Not Acceptable", +  407:"407 Proxy authorization needed", +  408:"408 Request timeout", +  409:"409 Conflict", +  410:"410 Gone", +  411:"411 Length Required", +  412:"412 Precondition Failed", +  413:"413 Request Entity Too Large", +  414:"414 Request-URI Too Large", +  415:"415 Unsupported Media Type", +  416:"416 Requested range not statisfiable", +  417:"417 Expectation Failed", +  418:"418 I'm a teapot", // Ha ha +  421:"421 Misdirected Request", +  422:"422 Unprocessable Entity", // WebDAV +  423:"423 Locked", // WebDAV +  424:"424 Failed Dependency", // WebDAV +  425:"425 Unordered Collection", // RFC3648 +  426:"426 Upgrade Required", // RFC2817 +  451:"451 Unavailable for Legal Reasons", // draft-tbray-http-legally-restricted-status +  +  // Internal Server Errors +  500:"500 Internal Server Error.", +  501:"501 Not Implemented", +  502:"502 Bad Gateway", +  503:"503 Service unavailable", +  504:"504 Gateway Timeout", +  505:"505 HTTP Version Not Supported", +  506:"506 Variant Also Negotiates", // RFC2295 +  507:"507 Insufficient Storage", // WebDAV / RFC4918 +  509:"509 Bandwidth Limit Exceeded", // An Apache defined extension in popular use +  510:"510 Not Extended", // RFC2774 +  598:"598 Network read timeout error", // Informal extension used by some HTTP proxies +  599:"599 Network connect timeout error", // Informal extension used by some HTTP proxies + ]); +  +    //! Makes an HTTP request through a proxy.   //!   //! @param proxy   //! URL for the proxy.   //!   //! @param user   //! @param password   //! Proxy authentication credentials.   //!   //! @param method
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:112:    if( query_variables )    url->set_query_variables( url->get_query_variables() +    query_variables );    string web_url = (string)url;       // Note: url object is wrecked here    url->host = proxy->host;    url->port = proxy->port;    query_variables = url->query = 0;    url->path = web_url; - #if constant(SSL.sslfile) + #if constant(SSL.File)    } else if (url->scheme == "https") {   #ifdef HTTP_QUERY_DEBUG    werror("Proxied SSL request.\n");   #endif    if (!con || (con->host != url->host) || (con->port != url->port)) {    // Make a CONNECT request to the proxy,    // and use keep-alive to stack the real request on top.    proxy->path = url->host + ":" + url->port;    if (!proxy_headers) proxy_headers = ([]);    proxy_headers->connection = "keep-alive";
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:137: Inside #if constant(SSL.sslfile)
   return con;    }    con->headers["connection"] = "keep-alive";    con->headers["content-length"] = "0";    con->host = url->host;    con->port = url->port;    con->https = 1;    con->start_tls(1);    }    proxy_headers = request_headers; - #endif + #endif /* constant(SSL.File) */    } else {    error("Can't handle proxying of %O.\n", url->scheme);    }       return do_method(method, url, query_variables, proxy_headers, con, data);   }      //! Low level HTTP call method.   //!   //! @param method
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:184:    url=Standards.URI(url);       if( (< "httpu", "httpmu" >)[url->scheme] ) {    return do_udp_method(method, url, query_variables, request_headers,    con, data);    }       if(!con)    con = .Query();    - #if constant(SSL.sslfile) + #if constant(SSL.File)    if(url->scheme!="http" && url->scheme!="https")    error("Can't handle %O or any other protocols than HTTP or HTTPS.\n",    url->scheme);       con->https = (url->scheme=="https")? 1 : 0;   #else    if(url->scheme!="http")    error("Can't handle %O or any other protocol than HTTP "    "(HTTPS requires Nettle support).\n",    url->scheme); - #endif + #endif /* constant(SSL.File) */    -  if(!request_headers) -  request_headers = ([]); +     mapping default_headers = ([    "user-agent" : "Mozilla/5.0 (compatible; MSIE 6.0; Pike HTTP client)"    " Pike/" + __REAL_MAJOR__ + "." + __REAL_MINOR__ + "." + __REAL_BUILD__,    "host" : url->host +    (url->port!=(url->scheme=="https"?443:80)?":"+url->port:"")]);    -  if(url->user || url->passwd) +  if(url->user || url->password)    default_headers->authorization = "Basic "    + MIME.encode_base64(url->user + ":" +    (url->password || "")); -  request_headers = default_headers | request_headers; +     -  +  if(!request_headers) +  request_headers = default_headers; +  else +  request_headers = default_headers | +  mkmapping(lower_case(indices(request_headers)[*]), +  values(request_headers)); +     string query=url->query;    if(query_variables && sizeof(query_variables))    {    if(query)    query+="&"+http_encode_query(query_variables);    else    query=http_encode_query(query_variables);    }       string path=url->path;    if(path=="") path="/";       con->sync_request(url->host,url->port,    method+" "+path+(query?("?"+query):"")+" HTTP/1.0",    request_headers, data);       if (!con->ok) {    if (con->errno) -  error ("I/O error: %s\n", strerror (con->errno)); +  error ("I/O error: %s.\n", strerror (con->errno));    return 0;    }    return con;   }      protected .Query do_udp_method(string method, Standards.URI url,    void|mapping(string:int|string|array(string)) query_variables,    void|mapping(string:string|array(string))    request_headers, void|Protocols.HTTP.Query con,    void|string data)
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:257:    path = "*";    else    path = "/";    }    string msg = method + " " + path + " HTTP/1.1\r\n";       Stdio.UDP udp = Stdio.UDP();    int port = 10000 + random(1000);    int i;    while(1) { -  if( !catch( udp->bind(port++) ) ) break; +  if( !catch( udp->bind(port++, 0, 1) ) ) break;    if( i++ > 1000 ) error("Could not open a UDP port.\n");    }    if(url->method=="httpmu") {    mapping ifs = Stdio.gethostip();    if(!sizeof(ifs)) error("No Internet interface found.\n");    foreach(ifs; string i; mapping data)    if(sizeof(data->ips)) {    udp->enable_multicast(data->ips[0]);    break;    }
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:316:    void|mapping(string:string|array(string)) request_headers,    Protocols.HTTP.Query con, void|string data)   {    if(stringp(url))    url=Standards.URI(url);       if( (< "httpu", "httpmu" >)[url->scheme] ) {    error("Asynchronous httpu or httpmu not yet supported.\n");    }    - #if constant(SSL.sslfile) + #if constant(SSL.File)    if(url->scheme!="http" && url->scheme!="https")    error("Can't handle %O or any other protocols than HTTP or HTTPS.\n",    url->scheme);       con->https = (url->scheme=="https")? 1 : 0;   #else    if(url->scheme!="http")    error("Can't handle %O or any other protocol than HTTP.\n",    url->scheme); - #endif + #endif /* constant(SSL.File) */       if(!request_headers)    request_headers = ([]);    mapping default_headers = ([    "user-agent" : "Mozilla/5.0 (compatible; MSIE 6.0; Pike HTTP client)"    " Pike/" + __REAL_MAJOR__ + "." + __REAL_MINOR__ + "." + __REAL_BUILD__,    "host" : url->host +    (url->port!=(url->scheme=="https"?443:80)?":"+url->port:"")]);    -  if(url->user || url->passwd) +  if(url->user || url->password)    default_headers->authorization = "Basic "    + MIME.encode_base64(url->user + ":" +    (url->password || ""));    request_headers = default_headers | request_headers;       string query=url->query;    if(query_variables && sizeof(query_variables))    {    if(query)    query+="&"+http_encode_query(query_variables);
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:480:    if( query_variables )    url->set_query_variables( url->get_query_variables() +    query_variables );    string web_url = (string)url;       // Note: url object is wrecked here    url->host = proxy->host;    url->port = proxy->port;    query_variables = url->query = 0;    url->path = web_url; - #if constant(SSL.sslfile) + #if constant(SSL.File)    } else if(url->scheme == "https") {   #ifdef HTTP_QUERY_DEBUG    werror("Proxied SSL request.\n");   #endif    if (!con || (con->host != url->host) || (con->port != url->port)) {    // Make a CONNECT request to the proxy,    // and use keep-alive to stack the real request on top.    proxy->path = url->host + ":" + url->port;    if (!proxy_headers) proxy_headers = ([]);    proxy_headers->connection = "keep-alive";
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:582:    void|Protocols.HTTP.Query con)   {    .Query c;    multiset seen = (<>);    do {    if(!url) return 0;    if(seen[url] || sizeof(seen)>1000) return 0;    seen[url]=1;    c = get_url(url, query_variables, request_headers, con);    if(!c) return 0; -  if(c->status==302) url = c->headers->location; +  if(c->status==302) +  url = Standards.URI(c->headers->location, url);    } while( c->status!=200 );    return ({ c->headers["content-type"], c->data() });   }      //! Returns the returned data after calling the requested server for   //! information through HTTP GET. @expr{0@} is returned upon failure.   //! Redirects (HTTP 302) are automatically followed.   //!   string get_url_data(string|Standards.URI url,    void|mapping(string:int|string|array(string)) query_variables,
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:650:      //! Encodes a query mapping to a string;   //! this protects odd - in http perspective - characters   //! like '&' and '#' and control characters,   //! and packs the result together in a HTTP query string.   //!   //! Example:   //! @pre{   //! > Protocols.HTTP.http_encode_query( (["anna":"eva","lilith":"blue"]) );   //! Result: "lilith=blue&anna=eva" - //! > Protocols.HTTP.http_encode_query( (["&amp;":"&","'=\"":"\0\0\0"]) ); - //! Result: "%26amp%3b=%26&%27%3d%22=%00%00%00" + //! > Protocols.HTTP.http_encode_query( (["&amp;":"&","'=\"":"\0\0\0\u0434"]) ); + //! Result: "%27%3D%22=%00%00%00%D0%B4&%26amp%3B=%26"   //! @}   string http_encode_query(mapping(string:int|string|array(string)) variables)   {    return Array.map((array)variables,    lambda(array(string|int|array(string)) v)    {    if (intp(v[1]))    return uri_encode(v[0]);    if (arrayp(v[1]))    return map(v[1], lambda (string val) {
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:688:   protected local constant other_chars =    (string) enumerate (0x20) + "\x7f" // Control chars    " \"<>\\^`{|}";      protected local constant eight_bit_chars = (string) enumerate (0x80, 1, 0x80);      string percent_encode (string s)   //! Encodes the given string using @tt{%XX@} encoding, except that URI   //! unreserved chars are not encoded. The unreserved chars are   //! @tt{A-Z@}, @tt{a-z@}, @tt{0-9@}, @tt{-@}, @tt{.@}, @tt{_@}, and - //! @tt{~@} (see RFC 2396 section 2.3). + //! @tt{~@} (see @rfc{2396:2.3@}).   //!   //! 8-bit chars are encoded straight, and wider chars are not allowed.   //! That means this encoding is applicable if @[s] is a binary octet   //! string. If it is a character string then @[uri_encode] should be   //! used instead.   //!   //! It is also slightly faster than @[uri_encode] if @[s] is known to   //! contain only US-ASCII.   {    constant replace_chars = (gen_delims + sub_delims +
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:728:   //! is necessary to work as the reverse of @[iri_encode].   {    return _Roxen.http_decode_string (s);   }      string uri_encode (string s)   //! Encodes the given string using @tt{%XX@} encoding to be used as a   //! component part in a URI. This means that all URI reserved and   //! excluded characters are encoded, i.e. everything except @tt{A-Z@},   //! @tt{a-z@}, @tt{0-9@}, @tt{-@}, @tt{.@}, @tt{_@}, and @tt{~@} (see - //! RFC 2396 section 2.3). + //! @rfc{2396:2.3@}).   //!   //! 8-bit chars and wider are encoded using UTF-8 followed by - //! percent-encoding. This follows RFC 3986 section 2.5, the - //! IRI-to-URI conversion method in the IRI standard (RFC 3987) and - //! appendix B.2 in the HTML 4.01 standard. It should work regardless - //! of the charset used in the XML document the URI might be inserted - //! into. + //! percent-encoding. This follows @rfc{3986:2.5@}, the IRI-to-URI + //! conversion method in the IRI standard (@rfc{3987@}) and appendix + //! B.2 in the HTML 4.01 standard. It should work regardless of the + //! charset used in the XML document the URI might be inserted into.   //!   //! @seealso   //! @[uri_decode], @[uri_encode_invalids], @[iri_encode]   {    return percent_encode (string_to_utf8 (s));   }      string uri_encode_invalids (string s)   //! Encodes all "dangerous" chars in the given string using @tt{%XX@}   //! encoding, so that it can be included as a URI in an HTTP message   //! or header field. This includes control chars, space and various - //! delimiter chars except those in the URI @tt{reserved@} set (RFC - //! 2396 section 2.2). + //! delimiter chars except those in the URI @tt{reserved@} set + //! (@rfc{2396:2.2@}).   //!   //! Since this function doesn't touch the URI @tt{reserved@} chars nor   //! the escape char @tt{%@}, it can be used on a complete formatted   //! URI or IRI.   //!   //! 8-bit chars and wider are encoded using UTF-8 followed by - //! percent-encoding. This follows RFC 3986 section 2.5, the IRI - //! standard (RFC 3987) and appendix B.2 in the HTML 4.01 standard. + //! percent-encoding. This follows @rfc{3986:2.5@}, the IRI standard + //! (@rfc{3987@}) and appendix B.2 in the HTML 4.01 standard.   //!   //! @note   //! The characters in the URI @tt{reserved@} set are: @tt{:@},   //! @tt{/@}, @tt{?@}, @tt{#@}, @tt{[@}, @tt{]@}, @tt{@@@}, @tt{!@},   //! @tt{$@}, @tt{&@}, @tt{'@}, @tt{(@}, @tt{)@}, @tt{*@}, @tt{+@},   //! @tt{,@}, @tt{;@}, @tt{=@}. In addition, this function doesn't   //! touch the escape char @tt{%@}.   //!   //! @seealso   //! @[uri_decode], @[uri_encode]
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:792:    // Note: This currently does not quite work for URI-to-IRI    // conversion according to RFC 3987 section 3.2. Most importantly    // any invalid utf8-sequences should be left percent-encoded in the    // result.    return utf8_to_string (_Roxen.http_decode_string (s));   }      string iri_encode (string s)   //! Encodes the given string using @tt{%XX@} encoding to be used as a   //! component part in an IRI (Internationalized Resource Identifier, - //! see RFC 3987). This means that all chars outside the IRI + //! see @rfc{3987@}). This means that all chars outside the IRI   //! @tt{iunreserved@} set are encoded, i.e. this function encodes   //! equivalently to @[uri_encode] except that all 8-bit and wider   //! characters are left as-is.   //!   //! @bugs   //! This function currently does not encode chars in the Unicode   //! private ranges, although that is strictly speaking required in   //! some but not all IRI components. That could change if it turns out   //! to be a problem.   //!
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:850: Inside #if 0
  //! @seealso   //! @[iri_decode], @[uri_normalize]   {    // FIXME   }      #endif      string quoted_string_encode (string s)   //! Encodes the given string quoted to be used as content inside a - //! @tt{quoted-string@} according to RFC 2616 section 2.2. The - //! returned string does not include the surrounding @tt{"@} chars. + //! @tt{quoted-string@} according to @rfc{2616:2.2@}. The returned + //! string does not include the surrounding @tt{"@} chars.   //!   //! @note - //! The @tt{quoted-string@} quoting rules in RFC 2616 have several + //! The @tt{quoted-string@} quoting rules in @rfc{2616@} have several   //! problems:   //!   //! @ul   //! @item   //! Quoting is inconsistent since @tt{"@} is quoted as @tt{\"@}, but   //! @tt{\@} does not need to be quoted. This is resolved in the HTTP   //! bis update to mandate quoting of @tt{\@} too, which this   //! function performs.   //!   //! @item
pike.git/lib/modules/Protocols.pmod/HTTP.pmod/module.pmod:878:   //! @endul   //!   //! @seealso   //! @[quoted_string_decode]   {    return replace (s, (["\"": "\\\"", "\\": "\\\\"]));   }      string quoted_string_decode (string s)   //! Decodes the given string which has been encoded as a - //! @tt{quoted-string@} according to RFC 2616 section 2.2. @[s] is - //! assumed to not include the surrounding @tt{"@} chars. + //! @tt{quoted-string@} according to @rfc{2616:2.2@}. @[s] is assumed + //! to not include the surrounding @tt{"@} chars.   //!   //! @seealso   //! @[quoted_string_encode]   {    return map (s / "\\\\", replace, "\\", "") * "\\";   } -  - // --- Compatibility code -  - __deprecated__ string http_encode_string(string in) - //! This is a deprecated alias for @[uri_encode], for compatibility - //! with Pike 7.6 and earlier. - //! - //! In 7.6 this function didn't handle 8-bit and wider chars - //! correctly. It encoded 8-bit chars directly to @tt{%XX@} escapes, - //! and it used nonstandard @tt{%uXXXX@} escapes for 16-bit chars. - //! - //! That is considered a bug, and hence the function is changed. If - //! you need the old buggy encoding then use the 7.6 compatibility - //! version (@expr{#pike 7.6@}). - //! - //! @deprecated uri_encode - { -  return uri_encode (in); - } -  - //! This function used to claim that it encodes the specified string - //! according to the HTTP cookie standard. If fact it does not - it - //! applies URI-style (i.e. @expr{%XX@}) encoding on some of the - //! characters that cannot occur literally in cookie values. There - //! exist some web servers (read Roxen and forks) that usually perform - //! a corresponding nonstandard decoding of %-style escapes in cookie - //! values in received requests. - //! - //! This function is deprecated. The function @[quoted_string_encode] - //! performs encoding according to the standard, but it is not safe to - //! use with arbitrary chars. Thus URI-style encoding using - //! @[uri_encode] or @[percent_encode] is normally a good choice, if - //! you can use @[uri_decode]/@[percent_decode] at the decoding end. - //! - //! @deprecated - __deprecated__ string http_encode_cookie(string f) - { -  return replace( -  f, -  ({ "\000", "\001", "\002", "\003", "\004", "\005", "\006", "\007", -  "\010", "\011", "\012", "\013", "\014", "\015", "\016", "\017", -  "\020", "\021", "\022", "\023", "\024", "\025", "\026", "\027", -  "\030", "\031", "\032", "\033", "\034", "\035", "\036", "\037", -  "\177", -  "\200", "\201", "\202", "\203", "\204", "\205", "\206", "\207", -  "\210", "\211", "\212", "\213", "\214", "\215", "\216", "\217", -  "\220", "\221", "\222", "\223", "\224", "\225", "\226", "\227", -  "\230", "\231", "\232", "\233", "\234", "\235", "\236", "\237", -  " ", "%", "'", "\"", ",", ";", "=", ":" }), -  ({ -  "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", -  "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", -  "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", -  "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", -  "%7f", -  "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", -  "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", -  "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", -  "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", -  "%20", "%25", "%27", "%22", "%2c", "%3b", "%3d", "%3a" })); - } -  - //! Helper function for replacing HTML entities with the corresponding - //! unicode characters. - //! @deprecated Parser.parse_html_entities - __deprecated__ string unentity(string s) - { -  return master()->resolv("Parser.parse_html_entities")(s,1); - } +