📄 url.cpp
字号:
} if(!stricmp(buffer, "Transfer-Encoding")) { if(!stricmp(cp, "chunked")) { chunk = 0; encoding = encodingChunked; } } httpHeader(buffer, cp); } return status;}void URLStream::close(void){ if(Socket::state == AVAILABLE) return; endStream(); so = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(so != INVALID_SOCKET) Socket::state = AVAILABLE;}URLStream::Error URLStream::sendHTTPHeader(const char *url, const char **vars, size_t buf){ // TODO: implement authentication char reloc[4096]; // "//" host ":" port == max 2 + 128 + 1 + 5 + 1(\0) = 137, rounded 140 char host[140]; // TODO: add support for //user:pass@host:port/ syntax#ifdef HAVE_SSTREAM ostringstream str;#else char buffer[4096]; strstream str(buffer, sizeof(buffer), ios::out);#endif char *ref, *cp, *ep; char *hp; const char *uri = "/"; int count = 0; size_t len = 0; tpport_t port = 80; const char **args = vars; const char *var; bool lasteq = true; struct servent *svc;retry:#ifdef HAVE_SSTREAM str.str() = "";#else buffer[0] = 0; str.seekp(0);#endif setString(host, sizeof(host), url); hp = strchr(host, '/'); while(*hp == '/') ++hp; cp = strchr(hp, '/'); if (cp) *cp = 0; ep = strrchr(hp, ':'); if(ep) { ++ep; if(isdigit(*ep)) port = atoi(ep); else { Socket::mutex.enter(); svc = getservbyname(ep, "tcp"); if(svc) port = ntohs(svc->s_port); Socket::mutex.leave(); } *ep = 0; } if(!proxyPort) { const char* ep1 = url; while(*ep1 == '/') ++ep1; ep1 = strchr(ep1, '/'); if(ep1) uri = ep1; } switch(urlmethod) { case methodHttpGet: str << "GET "; if(proxyPort) { str << "http:" << url; if(!cp) str << '/'; } else str << uri; break; case methodHttpPost: case methodHttpPostMultipart: str << "POST "; if(proxyPort) { str << "http:" << url; if(!cp) str << '/'; } else str << uri; break; default: return errInvalid; } if(vars && urlmethod == methodHttpGet) { str << "?"; while(*vars) { if(count++ && lasteq) str << "&"; str << *vars; if(!lasteq) lasteq = true; else if(strchr(*vars, '=')) lasteq = true; else { lasteq = false; str << "="; } ++vars; } } switch(protocol) { case protocolHttp1_1: str << " HTTP/1.1" << "\r\n"; break; case protocolHttp1_0: str << " HTTP/1.0" << "\r\n"; break; } if ( m_host.empty() ) m_host = hp; str << "Host: " << hp << "\r\n"; if(agent) str << "User-Agent: " << agent << "\r\n"; if(cookie) str << "Cookie: " << cookie << "\r\n"; if(pragma) str << "Pragma: " << pragma << "\r\n"; if(referer) str << "Referer: " << referer << "\r\n"; switch(auth) { case authBasic: str << "Authorization: Basic "; snprintf(reloc, 64, "%s:%s", user, password); b64Encode(reloc, reloc + 64, 128); str << reloc + 64 << "\r\n"; case authAnonymous: break; } switch(proxyAuth) { case authBasic: str << "Proxy-Authorization: Basic "; snprintf(reloc, 64, "%s:%s", proxyUser, proxyPasswd); b64Encode(reloc, reloc + 64, 128); str << reloc + 64 << "\r\n"; str << "Proxy-Connection: close" << "\r\n"; case authAnonymous: break; } str << "Connection: close\r\n"; char **add = extraHeader(); if(add) { while(*add) { str << *(add++) << ": "; str << *(add++) << "\r\n"; } } if(vars) switch(urlmethod) { case methodHttpPost: while(*args) { var = *args; if(count++ || !strchr(var, '=')) len += strlen(var) + 1; else len = strlen(var); ++args; } count = 0; len += 2; str << "Content-Type: application/x-www-form-urlencoded" << "\r\n"; str << "Content-Length: " << (unsigned)len << "\r\n"; break; case methodHttpPostMultipart: while(*args) str << *(args++) << "\r\n"; break; } str << "\r\n";#ifdef HAVE_SSTREAM // sstream does not want ends#else str << ends;#endif if(Socket::state != AVAILABLE) close();#ifndef WIN32#ifdef SOICGIFINDEX if (localif != NULL) { struct ifreq ifr; switch(family) {#ifdef CCXX_IPV6 case IPV6: sockaddr_in6 source; int alen = sizeof(source); memset(&ifr, 0, sizeof(ifr)); setString(ifr.ifr_name, sizeof(ifr.ifr_name), localif); if (ioctl(so, SIOCGIFINDEX, &ifr) < 0) return errInterface; else { if (setsockopt(so, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) return errInterface; else if(getsockname(so, (struct sockaddr*)&source,(socklen_t *) &alen) == -1) return errInterface; else if (bind(so, (struct sockaddr*)&source, sizeof(source)) == -1) return errInterface; else source.sin6_port = 0; } break;#endif default: sockaddr_in source; int alen = sizeof(source); memset(&ifr, 0, sizeof(ifr)); setString(ifr.ifr_name, sizeof(ifr.ifr_name), localif); if (ioctl(so, SIOCGIFINDEX, &ifr) < 0) return errInterface; else { if (setsockopt(so, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) return errInterface; else if(getsockname(so, (struct sockaddr*)&source,(socklen_t *) &alen) == -1) return errInterface; else if (bind(so, (struct sockaddr*)&source, sizeof(source)) == -1) return errInterface; else source.sin_port = 0; } } }#endif#endif if(proxyPort) { switch(family) {#ifdef CCXX_IPV6 case IPV6: connect(v6proxyHost, proxyPort, (unsigned)buf); break;#endif default: connect(proxyHost, proxyPort, (unsigned)buf); } } else { switch(family) {#ifdef CCXX_IPV6 case IPV6: connect(IPV6Host(hp), port, (unsigned)buf); break;#endif default: connect(IPV4Host(hp), port, (unsigned)buf); } } if(!isConnected()) return errUnreachable; // FIXME: send (or write) can send less than len bytes // use stream funcion ??#ifdef HAVE_SSTREAM ::send(so, str.str().c_str(), _IOLEN64 str.str().length(), 0);#else ::send(so, buffer, _IOLEN64 strlen(buffer), 0);#endif if(urlmethod == methodHttpPost && vars) {#ifdef HAVE_SSTREAM str.str() = "";#else str.seekp(0);#endif bool sep = false; while(*vars) { if(sep) ::send(so, "&", 1,0); else sep = true; var = *vars; if(!strchr(var, '=')) { snprintf(reloc, sizeof(reloc), "%s=%s", var, *(++vars)); ::send(so, reloc, _IOLEN64 strlen(reloc), 0); } else ::send(so, var, _IOLEN64 strlen(var),0); ++vars; } ::send(so, "\r\n", 2, 0); }cont:#ifdef HAVE_SSTREAM char buffer[4096];#else // nothing here#endif len = readLine(buffer, sizeof(buffer) - 1, timeout); if(len < 1) return errTimeout; if(strnicmp(buffer, "HTTP/", 5)) return errInvalid; ref = strchr(buffer, ' '); while(*ref == ' ') ++ref; switch(atoi(ref)) { default: return errInvalid; case 100: goto cont; case 200: return errSuccess; case 401: return errUnauthorized; case 403: return errForbidden; case 404: return errMissing; case 405: return errDenied; case 500: case 501: case 502: case 503: case 504: case 505: return errFailure; case 300: case 301: case 302: break; } if(!follow) return errRelocated; for(;;) { len = readLine(reloc, sizeof(reloc), timeout); if(len < 1) return errTimeout; if(!strnicmp(reloc, "Location: ", 10)) break; } if(!strnicmp(reloc + 10, "http:", 5)) { url = strchr(reloc + 15, '/'); ep = (char *)(url + strlen(url) - 1); while(*ep == '\r' || *ep == '\n') *(ep--) = 0; } else url = reloc + 10; close(); goto retry;}void URLStream::setAuthentication(Authentication a, const char *value){ auth = a; if (auth != authAnonymous) { if(!user) user = "anonymous"; if(!password) password = ""; }}void URLStream::setProxyAuthentication(Authentication a, const char *value){ proxyAuth = a; if (proxyAuth != authAnonymous) { if(!proxyUser) proxyUser = "anonymous"; if(!proxyPasswd) proxyPasswd = ""; }}void URLStream::setReferer(const char *str){ if(!str) return; referer = str;}#ifdef CCXX_NAMESPACES}#endif/** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -