⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 urlstorage.cxx

📁 SP是一个基于GNU C++编译器
💻 CXX
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) 1995 James Clark// See the file COPYING for copying permission.#ifdef __GNUG__#pragma implementation#endif// FIXME This implementation won't work on an EBCDIC machine.#include "splib.h"#ifdef WINSOCK#include <winsock.h>#define readsocket(s, p, n) ::recv(s, p, n, 0)#define writesocket(s, p, n) ::send(s, p, n, 0)#define errnosocket (WSAGetLastError())#define SocketMessageArg(n) WinsockMessageArg(n)#define SOCKET_EINTR (WSAEINTR)#define SP_HAVE_SOCKET#else#ifdef SP_HAVE_SOCKET#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#ifdef SP_INCLUDE_UNISTD_H#include <unistd.h>#endif#ifdef SP_INCLUDE_OSFCN_H#include <osfcn.h>#endif#ifdef SP_DECLARE_H_ERRNOextern int h_errno;#endiftypedef int SOCKET;#define SOCKET_ERROR (-1)#define INVALID_SOCKET (-1)#define SOCKET_EINTR (EINTR)#define closesocket(s) close(s)#define writesocket(fd, p, n) ::write(fd, p, n)#define readsocket(s, p, n) ::read(s, p, n)#define errnosocket (errno)#define SocketMessageArg(n) ErrnoMessageArg(n)#include "ErrnoMessageArg.h"#endif /* SP_HAVE_SOCKET */#endif /* not WINSOCK */#include "URLStorage.h"#include "URLStorageMessages.h"#include "RewindStorageObject.h"#include "UnivCharsetDesc.h"#include "MessageArg.h"#include "MessageBuilder.h"#include "macros.h"#include <stdlib.h>#include <string.h>#include <errno.h>#include <stddef.h>#include <ctype.h>#include <stdio.h>#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifstatic UnivCharsetDesc::Range range = { 0, 128, 0 };static CharsetInfo iso646Charset(UnivCharsetDesc(&range, 1));#ifdef SP_HAVE_SOCKETclass HttpSocketStorageObject : public RewindStorageObject {public:  HttpSocketStorageObject(SOCKET fd, Boolean mayRewind, const StringC &hostStr);  ~HttpSocketStorageObject();  Boolean open(const String<char> &path, Messenger &);  Boolean read(char *buf, size_t bufSize, Messenger &mgr, size_t &nread);  Boolean seekToStart(Messenger &);  static SOCKET openHttp(const String<char> &host,			 unsigned short port,			 const StringC &hostStr,			 Messenger &mgr);private:  HttpSocketStorageObject(const HttpSocketStorageObject &); // undefined  void operator=(const HttpSocketStorageObject &); // undefined  Boolean readHeader(Messenger &);  Boolean readLine(Messenger &mgr, String<char> &line, String<char> &leftOver);  static Boolean parseStatus(const char *&ptr, int &val);  StringC hostStr_;  String<char> path_;  Boolean eof_;  SOCKET fd_;};#ifdef WINSOCKclass WinsockMessageArg : public MessageArg {public:  WinsockMessageArg(int n) : n_(n) { }  MessageArg *copy() const { return new WinsockMessageArg(*this); }  void append(MessageBuilder &) const;private:  int n_;};void WinsockMessageArg::append(MessageBuilder &builder) const{  // I can't figure out how to get a string associated  // with this error number.  FormatMessage() doesn't seem  // to work.  builder.appendFragment(URLStorageMessages::winsockErrorNumber);  builder.appendNumber(n_);}class WinsockIniter {public:  WinsockIniter();  ~WinsockIniter();  Boolean init(Messenger &mgr);private:  Boolean inited_;  Boolean initSuccess_;};static WinsockIniter winsockIniter;WinsockIniter::WinsockIniter(): inited_(0){}WinsockIniter::~WinsockIniter(){  if (inited_ && initSuccess_)    (void)WSACleanup();}Boolean WinsockIniter::init(Messenger &mgr){  if (!inited_) {    inited_ = 1;    initSuccess_ = 0;    WORD version = MAKEWORD(1, 1);    WSADATA wsaData;    int err = WSAStartup(version, &wsaData);    if (err)      mgr.message(URLStorageMessages::winsockInitialize,		  WinsockMessageArg(err));    else if (LOBYTE(wsaData.wVersion) != 1	     || HIBYTE(wsaData.wVersion) != 1) {      mgr.message(URLStorageMessages::winsockVersion);      WSACleanup();    }    else      initSuccess_ = 1;  }  return initSuccess_;}#endif /* WINSOCK */#endif /* SP_HAVE_SOCKET */URLStorageManager::URLStorageManager(const char *type): type_(type), IdStorageManager(&iso646Charset){}const char *URLStorageManager::type() const{  return type_;}Boolean URLStorageManager::guessIsId(const StringC &id,				     const CharsetInfo &charset) const{  if (id.size() < 8)    return 0;  size_t i = 0;  for (const char *s = "http://"; *s; s++, i++)    if (id[i] != charset.execToDesc(*s)	&& (!islower(*s) || id[i] != charset.execToDesc(toupper(*s))))      return 0;  return 1;}StorageObject *URLStorageManager::makeStorageObject(const StringC &specId,						    const StringC &baseId,						    Boolean,						    Boolean mayRewind,						    Messenger &mgr,						    StringC &id){#ifdef SP_HAVE_SOCKET  id = specId;  resolveRelative(baseId, id, 0);  if (id.size() < 5      || (id[0] != 'h' && id[0] != 'H')      || (id[1] != 't' && id[1] != 'T')      || (id[2] != 't' && id[2] != 'T')      || (id[3] != 'p' && id[3] != 'P')      || id[4] != ':') {    mgr.message(URLStorageMessages::onlyHTTP);    return 0;  }  if (id.size() < 7 || id[5] != '/' || id[6] != '/') {    mgr.message(URLStorageMessages::badRelative,		StringMessageArg(id));    return 0;  }  size_t i = 7;  String<char> host;  while (i < id.size()) {    if (id[i] == '/')      break;    if (id[i] == ':')      break;    host += char(id[i]);    i++;  }  if (host.size() == 0) {    mgr.message(URLStorageMessages::emptyHost,		StringMessageArg(id));    return 0;  }  unsigned short port;  if (i < id.size() && id[i] == ':') {    i++;    String<char> digits;    while (i < id.size() && id[i] != '/') {      digits += char(id[i]);      i++;    }    if (digits.size() == 0) {      mgr.message(URLStorageMessages::emptyPort,		  StringMessageArg(id));      return 0;    }    digits += '\0';    char *endptr;    long n = strtol(digits.data(), &endptr, 10);    if (endptr != digits.data() + digits.size() - 1	|| n < 0	|| n > 65535L) {      mgr.message(URLStorageMessages::invalidPort,		  StringMessageArg(id));      return 0;    }    port = (unsigned short)n;  }  else    port = 80;  String<char> path;  if (i < id.size()) {    while (i < id.size() && id[i] != '#') {      path += char(id[i]);      i++;    }  }  if (path.size() == 0)    path += '/';  StringC hostStr;  for (i = 0; i < host.size(); i++)    hostStr += host[i];  host += '\0';  SOCKET fd = HttpSocketStorageObject::openHttp(host, port, hostStr, mgr);  if (fd == INVALID_SOCKET)    return 0;  HttpSocketStorageObject *p    = new HttpSocketStorageObject(fd, mayRewind, hostStr);  if (!p->open(path, mgr)) {    delete p;    return 0;  }  return p;#else /* not SP_HAVE_SOCKET */  ParentLocationMessenger(mgr).message(URLStorageMessages::notSupported);  return 0;#endif /* not SP_HAVE_SOCKET */}Boolean URLStorageManager::resolveRelative(const StringC &baseId,					   StringC &id,					   Boolean) const{  static const char schemeChars[] =     "abcdefghijklmnopqrstuvwxyz"    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    "01234567879"    "+-.";  size_t i;  // If it has a scheme, it is absolute.  for (i = 0; i < id.size(); i++) {    if (id[i] == ':') {      if (i == 0)	break;      else	return 1;    }    else if (!strchr(schemeChars, id[i]))      break;  }  for (i = 0; i < id.size(); i++) {    if (id[i] != '/')      break;  }  size_t slashCount = i;  if (slashCount > 0) {    Boolean foundSameSlash = 0;    size_t sameSlashPos;    for (size_t j = 0; j < baseId.size(); j++) {      size_t thisSlashCount = 0;      for (size_t k = j; k < baseId.size() && baseId[k] == '/'; k++)	thisSlashCount++;      if (thisSlashCount == slashCount && !foundSameSlash) {	foundSameSlash = 1;	sameSlashPos = j;      }      else if (thisSlashCount > slashCount)	foundSameSlash = 0;    }    if (foundSameSlash) {      StringC tem(baseId.data(), sameSlashPos);      tem += id;      tem.swap(id);    }  }  else {    size_t j;    for (j = baseId.size(); j > 0; j--)      if (baseId[j - 1] == '/')	break;    if (j > 0) {      StringC tem(baseId.data(), j);      tem += id;      tem.swap(id);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -