📄 url.cpp
字号:
// Copyright (C) 2001-2005 Open Source Telecom Corporation.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by// the GNU General Public License. //// This exception applies only to the code released under the name GNU// Common C++. If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include <cc++/config.h>#ifdef CCXX_WITHOUT_EXTRAS#include <cc++/export.h>#endif#include <cc++/file.h>#include <cc++/thread.h>#include <cc++/exception.h>#include <cc++/address.h>#include <cc++/socket.h>#ifndef CCXX_WITHOUT_EXTRAS#include <cc++/export.h>#endif#include <cc++/url.h>#include <string>#include <cstdio>#include <cstdlib>#include <fcntl.h>#include <cerrno>#include <iostream>#ifdef WIN32#include <io.h>#endif#ifdef HAVE_SSTREAM#include <sstream>#else#include <strstream>#endif#include <cctype>#ifndef WIN32// cause problem on Solaris#if !defined(__sun) && !defined(__SUN__)#ifdef HAVE_NET_IF_H#include <net/if.h>#endif#endif#include <sys/ioctl.h>#endif#ifdef CCXX_NAMESPACESnamespace ost {using namespace std;#endifURLStream::URLStream(Family fam, timeout_t to) :TCPStream(fam){ persistent = false; proxyPort = 0; timeout = to; protocol = protocolHttp1_0; follow = true; proxyAuth = authAnonymous; encoding = encodingBinary; proxyUser = proxyPasswd = NULL; auth = authAnonymous; cookie = agent = pragma = referer = user = password = NULL; localif = NULL; setError(false);}int URLStream::aRead(char *buffer, size_t len, timeout_t timer){#ifndef __MINGW32__ return ::read((int)so, buffer, _IOLEN64 len);#else return ::recv(so, buffer, _IOLEN64 len, 0);#endif}int URLStream::aWrite(char *buffer, size_t len, timeout_t timer){#ifndef __MINGW32__ return ::write((int)so, buffer, _IOLEN64 len);#else return ::send((int)so, buffer, _IOLEN64 len, 0);#endif}void URLStream::httpHeader(const char *header, const char *value){}char **URLStream::extraHeader(void){ return NULL;}int URLStream::underflow(void){ ssize_t len, rlen; char *buf; if(bufsize == 1) return TCPStream::underflow(); if(!gptr()) return EOF; if(gptr() < egptr()) return (unsigned char)*gptr(); rlen = (ssize_t)((gbuf + bufsize) - eback()); if(encoding == encodingChunked) { buf = (char *)eback(); *buf = '\n'; while(!chunk && (*buf == '\n' || *buf == '\r')) { *buf = 0; len = readLine(buf, rlen, timeout); } if(len) { if(!chunk) chunk = strtol(buf, NULL, 16); if(rlen > (int)chunk) rlen = chunk; } else rlen = -1; } if(rlen > 0) { if(Socket::state == STREAM) rlen = aRead((char *)eback(), rlen, timeout); else if(timeout) { if(Socket::isPending(pendingInput, timeout)) rlen = ::recv(so, (char *)eback(), rlen, 0); else rlen = -1; } else rlen = ::recv(so, (char *)eback(), rlen, 0); } if(encoding == encodingChunked && rlen > 0) chunk -= rlen; if(rlen < 1) { if(rlen < 0) clear(ios::failbit | rdstate()); return EOF; } setg(eback(), eback(), eback() + rlen); return (unsigned char)*gptr();} void URLStream::setProxy(const char *host, tpport_t port){ switch(family) {#ifdef CCXX_IPV6 case IPV6: v6proxyHost = host; break;#endif case IPV4: proxyHost = host; } proxyPort = port;}URLStream::Error URLStream::submit(const char *path, const char **vars, size_t buf){ Error status = errInvalid, saved; if(!strnicmp(path, "http:", 5)) { urlmethod = methodHttpGet; path = strchr(path + 5, '/'); status = sendHTTPHeader(path, vars, buf); } if((status == errInvalid || status == errTimeout)) { if(Socket::state != AVAILABLE) close(); return status; } else { saved = status; status = getHTTPHeaders(); if(status == errSuccess) return saved; else if(status == errTimeout) { if(Socket::state != AVAILABLE) close(); } return status; }}URLStream::Error URLStream::post(const char *path, MIMEMultipartForm &form, size_t buf){ Error status = errInvalid, saved; if(!strnicmp(path, "http:", 5)) { urlmethod = methodHttpPostMultipart; path = strchr(path + 5, '/'); status = sendHTTPHeader(path, (const char **)form.getHeaders(), buf); } if(status == errInvalid || status == errTimeout) { if(Socket::state != AVAILABLE) close(); return status; } saved = status; status = getHTTPHeaders(); if(status == errSuccess) { form.body(dynamic_cast<std::ostream *>(this)); return saved; } if(status == errTimeout) { if(Socket::state != AVAILABLE) close(); } return status;}URLStream::Error URLStream::post(const char *path, const char **vars, size_t buf){ Error status = errInvalid, saved; if(!strnicmp(path, "http:", 5)) { urlmethod = methodHttpPost; path = strchr(path + 5, '/'); status = sendHTTPHeader(path, vars, buf); } if((status == errInvalid || status == errTimeout)) { if(Socket::state != AVAILABLE) close(); return status; } saved = status; status = getHTTPHeaders(); if(status == errSuccess) return saved; if(status == errTimeout) { if(Socket::state != AVAILABLE) close(); } return status;}URLStream::Error URLStream::head(const char *path, size_t buf){ Error status = errInvalid, saved; if(!strnicmp(path, "http:", 5)) { urlmethod = methodHttpGet; path = strchr(path + 5, '/'); status = sendHTTPHeader(path, NULL, buf); } if((status == errInvalid || status == errTimeout)) { if(Socket::state != AVAILABLE) close(); return status; } else { saved = status; status = getHTTPHeaders(); if(status == errSuccess) return saved; else if(status == errTimeout) { if(Socket::state != AVAILABLE) close(); } return status; }}URLStream &URLStream::getline(char *buffer, size_t size){ size_t len; *buffer = 0; // TODO: check, we mix use of streambuf with Socket::readLine... iostream::getline(buffer, (unsigned long)size); len = strlen(buffer); while(len) { if(buffer[len - 1] == '\r' || buffer[len - 1] == '\n') buffer[len - 1] = 0; else break; --len; } return *this;}URLStream::Error URLStream::get(size_t buffer){ String path = String("http://") + m_host; if ( m_address.operator[](0) != '/' ) path += "/"; path += m_address; return get(path.c_str(), buffer);}URLStream::Error URLStream::get(const char *urlpath, size_t buf){ const char *path = urlpath; Error status = errInvalid, saved; urlmethod = methodFileGet; if(Socket::state != AVAILABLE) close(); if(!strnicmp(path, "file:", 5)) { urlmethod = methodFileGet; path += 5; } else if(!strnicmp(path, "http:", 5)) { urlmethod = methodHttpGet; path = strchr(path + 5, '/'); } switch(urlmethod) { case methodHttpGet: status = sendHTTPHeader(path, NULL, buf); break; case methodFileGet: if(so != INVALID_SOCKET) ::close((int)so); so = ::open(path, O_RDWR); if(so == INVALID_SOCKET) so = ::open(path, O_RDONLY); // FIXME: open return the same handle type as socket call ?? if(so == INVALID_SOCKET) return errInvalid; Socket::state = STREAM; allocate(buf); return errSuccess; case methodHttpPut: case methodHttpPost: case methodHttpPostMultipart: case methodFtpGet: case methodFtpPut: case methodFilePut: break; } if((status == errInvalid || status == errTimeout)) { if(Socket::state != AVAILABLE) close(); return status; } else { saved = status; status = getHTTPHeaders(); if(status == errSuccess) return saved; else if(status == errTimeout) { if(Socket::state != AVAILABLE) close(); } return status; }}URLStream::Error URLStream::getHTTPHeaders(){ char buffer[512]; size_t buf = sizeof(buffer); Error status = errSuccess; char *cp, *ep; ssize_t len = 1; char nc = 0; chunk = ((unsigned)-1) / 2; encoding = encodingBinary; while(len > 0) { len = readLine(buffer, buf, timeout); if(len < 1) return errTimeout; // FIXME: for multiline syntax ?? if(buffer[0] == ' ' || buffer[0] == '\r' || buffer[0] == '\n') break; cp = strchr(buffer, ':'); if(!cp) continue; *(cp++) = 0; while(*cp == ' ' || *cp == '\t') ++cp; ep = strchr(cp, '\n'); if(!ep) ep = &nc; while(*ep == '\n' || *ep == '\r' || *ep == ' ') { *ep = 0; if((--ep) < cp) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -