|
Packit |
8a864e |
// Copyright (c) 1995 James Clark
|
|
Packit |
8a864e |
// See the file COPYING for copying permission.
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef __GNUG__
|
|
Packit |
8a864e |
#pragma implementation
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// FIXME This implementation won't work on an EBCDIC machine.
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#include "splib.h"
|
|
Packit |
8a864e |
#ifdef WINSOCK
|
|
Packit |
8a864e |
#include <winsock.h>
|
|
Packit |
8a864e |
#define readsocket(s, p, n) ::recv(s, p, n, 0)
|
|
Packit |
8a864e |
#define writesocket(s, p, n) ::send(s, p, n, 0)
|
|
Packit |
8a864e |
#define errnosocket (WSAGetLastError())
|
|
Packit |
8a864e |
#define SocketMessageArg(n) WinsockMessageArg(n)
|
|
Packit |
8a864e |
#define SOCKET_EINTR (WSAEINTR)
|
|
Packit |
8a864e |
#define SP_HAVE_SOCKET
|
|
Packit |
8a864e |
#else
|
|
Packit |
8a864e |
#ifdef SP_HAVE_SOCKET
|
|
Packit |
8a864e |
#include <stdio.h>
|
|
Packit |
8a864e |
#include <sys/types.h>
|
|
Packit |
8a864e |
#include <sys/socket.h>
|
|
Packit |
8a864e |
#include <netdb.h>
|
|
Packit |
8a864e |
#include <netinet/in.h>
|
|
Packit |
8a864e |
#include <arpa/inet.h>
|
|
Packit |
8a864e |
#ifdef SP_INCLUDE_UNISTD_H
|
|
Packit |
8a864e |
#include <unistd.h>
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef SP_INCLUDE_OSFCN_H
|
|
Packit |
8a864e |
#include <osfcn.h>
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef SP_DECLARE_H_ERRNO
|
|
Packit |
8a864e |
extern int h_errno;
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
typedef int SOCKET;
|
|
Packit |
8a864e |
#define SOCKET_ERROR (-1)
|
|
Packit |
8a864e |
#define INVALID_SOCKET (-1)
|
|
Packit |
8a864e |
#define SOCKET_EINTR (EINTR)
|
|
Packit |
8a864e |
#define closesocket(s) close(s)
|
|
Packit |
8a864e |
#define writesocket(fd, p, n) ::write(fd, p, n)
|
|
Packit |
8a864e |
#define readsocket(s, p, n) ::read(s, p, n)
|
|
Packit |
8a864e |
#define errnosocket (errno)
|
|
Packit |
8a864e |
#define SocketMessageArg(n) ErrnoMessageArg(n)
|
|
Packit |
8a864e |
#include "ErrnoMessageArg.h"
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#endif /* SP_HAVE_SOCKET */
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#endif /* not WINSOCK */
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#include "URLStorage.h"
|
|
Packit |
8a864e |
#include "URLStorageMessages.h"
|
|
Packit |
8a864e |
#include "RewindStorageObject.h"
|
|
Packit |
8a864e |
#include "UnivCharsetDesc.h"
|
|
Packit |
8a864e |
#include "MessageArg.h"
|
|
Packit |
8a864e |
#include "MessageBuilder.h"
|
|
Packit |
8a864e |
#include "macros.h"
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#include <stdlib.h>
|
|
Packit |
8a864e |
#include <string.h>
|
|
Packit |
8a864e |
#include <errno.h>
|
|
Packit |
8a864e |
#include <stddef.h>
|
|
Packit |
8a864e |
#include <ctype.h>
|
|
Packit |
8a864e |
#include <stdio.h>
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef SP_NAMESPACE
|
|
Packit |
8a864e |
namespace SP_NAMESPACE {
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
static UnivCharsetDesc::Range range = { 0, 128, 0 };
|
|
Packit |
8a864e |
static CharsetInfo iso646Charset(UnivCharsetDesc(&range, 1));
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef SP_HAVE_SOCKET
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
typedef enum {
|
|
Packit |
8a864e |
HTTP_OK ,
|
|
Packit |
8a864e |
HTTP_REDIRECT ,
|
|
Packit |
8a864e |
HTTP_ERROR
|
|
Packit |
8a864e |
} HTTP_RESPONSE_TYPE ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
class HttpSocketStorageObject : public RewindStorageObject {
|
|
Packit |
8a864e |
public:
|
|
Packit |
8a864e |
HttpSocketStorageObject(SOCKET fd, Boolean mayRewind, const StringC &hostStr);
|
|
Packit |
8a864e |
~HttpSocketStorageObject();
|
|
Packit |
8a864e |
HTTP_RESPONSE_TYPE open(const String<char> &host,
|
|
Packit |
8a864e |
unsigned short port,
|
|
Packit |
8a864e |
const String<char> &path,
|
|
Packit |
8a864e |
Messenger &,
|
|
Packit |
8a864e |
char[]);
|
|
Packit |
8a864e |
Boolean read(char *buf, size_t bufSize, Messenger &mgr, size_t &nread);
|
|
Packit |
8a864e |
Boolean seekToStart(Messenger &);
|
|
Packit |
8a864e |
static SOCKET openHttp(const String<char> &host,
|
|
Packit |
8a864e |
unsigned short port,
|
|
Packit |
8a864e |
const StringC &hostStr,
|
|
Packit |
8a864e |
Messenger &mgr);
|
|
Packit |
8a864e |
private:
|
|
Packit |
8a864e |
HttpSocketStorageObject(const HttpSocketStorageObject &); // undefined
|
|
Packit |
8a864e |
void operator=(const HttpSocketStorageObject &); // undefined
|
|
Packit |
8a864e |
HTTP_RESPONSE_TYPE readHeader(Messenger &, char[]);
|
|
Packit |
8a864e |
Boolean readLine(Messenger &mgr, String<char> &line, String<char> &leftOver);
|
|
Packit |
8a864e |
static Boolean parseStatus(const char *&ptr, int &val;;
|
|
Packit |
8a864e |
StringC hostStr_;
|
|
Packit |
8a864e |
String<char> path_;
|
|
Packit |
8a864e |
Boolean eof_;
|
|
Packit |
8a864e |
SOCKET fd_;
|
|
Packit |
8a864e |
};
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef WINSOCK
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
class WinsockMessageArg : public MessageArg {
|
|
Packit |
8a864e |
public:
|
|
Packit |
8a864e |
WinsockMessageArg(int n) : n_(n) { }
|
|
Packit |
8a864e |
MessageArg *copy() const { return new WinsockMessageArg(*this); }
|
|
Packit |
8a864e |
void append(MessageBuilder &) const;
|
|
Packit |
8a864e |
private:
|
|
Packit |
8a864e |
int n_;
|
|
Packit |
8a864e |
};
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
void WinsockMessageArg::append(MessageBuilder &builder) const
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
// I can't figure out how to get a string associated
|
|
Packit |
8a864e |
// with this error number. FormatMessage() doesn't seem
|
|
Packit |
8a864e |
// to work.
|
|
Packit |
8a864e |
builder.appendFragment(URLStorageMessages::winsockErrorNumber);
|
|
Packit |
8a864e |
builder.appendNumber(n_);
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
class WinsockIniter {
|
|
Packit |
8a864e |
public:
|
|
Packit |
8a864e |
WinsockIniter();
|
|
Packit |
8a864e |
~WinsockIniter();
|
|
Packit |
8a864e |
Boolean init(Messenger &mgr);
|
|
Packit |
8a864e |
private:
|
|
Packit |
8a864e |
Boolean inited_;
|
|
Packit |
8a864e |
Boolean initSuccess_;
|
|
Packit |
8a864e |
};
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
static WinsockIniter winsockIniter;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
WinsockIniter::WinsockIniter()
|
|
Packit |
8a864e |
: inited_(0)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
WinsockIniter::~WinsockIniter()
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
if (inited_ && initSuccess_)
|
|
Packit |
8a864e |
(void)WSACleanup();
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean WinsockIniter::init(Messenger &mgr)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
if (!inited_) {
|
|
Packit |
8a864e |
inited_ = 1;
|
|
Packit |
8a864e |
initSuccess_ = 0;
|
|
Packit |
8a864e |
WORD version = MAKEWORD(1, 1);
|
|
Packit |
8a864e |
WSADATA wsaData;
|
|
Packit |
8a864e |
int err = WSAStartup(version, &wsaData);
|
|
Packit |
8a864e |
if (err)
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::winsockInitialize,
|
|
Packit |
8a864e |
WinsockMessageArg(err));
|
|
Packit |
8a864e |
else if (LOBYTE(wsaData.wVersion) != 1
|
|
Packit |
8a864e |
|| HIBYTE(wsaData.wVersion) != 1) {
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::winsockVersion);
|
|
Packit |
8a864e |
WSACleanup();
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else
|
|
Packit |
8a864e |
initSuccess_ = 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
return initSuccess_;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#endif /* WINSOCK */
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#endif /* SP_HAVE_SOCKET */
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
URLStorageManager::URLStorageManager(const char *type)
|
|
Packit |
8a864e |
: type_(type), IdStorageManager(&iso646Charset)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
const char *URLStorageManager::type() const
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
return type_;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean URLStorageManager::guessIsId(const StringC &id,
|
|
Packit |
8a864e |
const CharsetInfo &charset) const
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
if (id.size() < 8)
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
size_t i = 0;
|
|
Packit |
8a864e |
for (const char *s = "http://"; *s; s++, i++)
|
|
Packit |
8a864e |
if (id[i] != charset.execToDesc(*s)
|
|
Packit |
8a864e |
&& (!islower(*s) || id[i] != charset.execToDesc(toupper(*s))))
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
inline int strdiff(const char* str, char* buf) {
|
|
Packit |
8a864e |
if ( ! *buf )
|
|
Packit |
8a864e |
return 1 ;
|
|
Packit |
8a864e |
if ( strlen(buf) <= strlen (str) )
|
|
Packit |
8a864e |
return 2 ;
|
|
Packit |
8a864e |
// if ( strncasecmp(buf, str, strlen(str)) )
|
|
Packit |
8a864e |
for ( int i = 0; i < strlen(str); ++i)
|
|
Packit |
8a864e |
if ( tolower(buf[i]) != tolower(str[i]) )
|
|
Packit |
8a864e |
return 3 ;
|
|
Packit |
8a864e |
return 0 ;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
StorageObject *URLStorageManager::makeStorageObject(const StringC &specId,
|
|
Packit |
8a864e |
const StringC &baseId,
|
|
Packit |
8a864e |
Boolean,
|
|
Packit |
8a864e |
Boolean mayRewind,
|
|
Packit |
8a864e |
Messenger &mgr,
|
|
Packit |
8a864e |
StringC &id)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
#ifdef SP_HAVE_SOCKET
|
|
Packit |
8a864e |
id = specId;
|
|
Packit |
8a864e |
resolveRelative(baseId, id, 0);
|
|
Packit |
8a864e |
if (id.size() < 5
|
|
Packit |
8a864e |
|| (id[0] != 'h' && id[0] != 'H')
|
|
Packit |
8a864e |
|| (id[1] != 't' && id[1] != 'T')
|
|
Packit |
8a864e |
|| (id[2] != 't' && id[2] != 'T')
|
|
Packit |
8a864e |
|| (id[3] != 'p' && id[3] != 'P')
|
|
Packit |
8a864e |
|| id[4] != ':') {
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::onlyHTTP);
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (id.size() < 7 || id[5] != '/' || id[6] != '/') {
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::badRelative,
|
|
Packit |
8a864e |
StringMessageArg(id));
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
size_t i = 7;
|
|
Packit |
8a864e |
String<char> host;
|
|
Packit |
8a864e |
while (i < id.size()) {
|
|
Packit |
8a864e |
if (id[i] == '/')
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
if (id[i] == ':')
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
host += char(id[i]);
|
|
Packit |
8a864e |
i++;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (host.size() == 0) {
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::emptyHost,
|
|
Packit |
8a864e |
StringMessageArg(id));
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
unsigned short port;
|
|
Packit |
8a864e |
if (i < id.size() && id[i] == ':') {
|
|
Packit |
8a864e |
i++;
|
|
Packit |
8a864e |
String<char> digits;
|
|
Packit |
8a864e |
while (i < id.size() && id[i] != '/') {
|
|
Packit |
8a864e |
digits += char(id[i]);
|
|
Packit |
8a864e |
i++;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (digits.size() == 0) {
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::emptyPort,
|
|
Packit |
8a864e |
StringMessageArg(id));
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
digits += '\0';
|
|
Packit |
8a864e |
char *endptr;
|
|
Packit |
8a864e |
long n = strtol(digits.data(), &endptr, 10);
|
|
Packit |
8a864e |
if (endptr != digits.data() + digits.size() - 1
|
|
Packit |
8a864e |
|| n < 0
|
|
Packit |
8a864e |
|| n > 65535L) {
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::invalidPort,
|
|
Packit |
8a864e |
StringMessageArg(id));
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
port = (unsigned short)n;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else
|
|
Packit |
8a864e |
port = 80;
|
|
Packit |
8a864e |
String<char> path;
|
|
Packit |
8a864e |
if (i < id.size()) {
|
|
Packit |
8a864e |
while (i < id.size() && id[i] != '#') {
|
|
Packit |
8a864e |
path += char(id[i]);
|
|
Packit |
8a864e |
i++;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
for ( int tries=0; tries<20; ++tries ) {
|
|
Packit |
8a864e |
if (path.size() == 0)
|
|
Packit |
8a864e |
path += '/';
|
|
Packit |
8a864e |
StringC hostStr;
|
|
Packit |
8a864e |
for (i = 0; i < host.size(); i++)
|
|
Packit |
8a864e |
hostStr += host[i];
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// Support HTTP redirect but limit number against an infinite loop
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
SOCKET fd = HttpSocketStorageObject::openHttp(host, port, hostStr, mgr);
|
|
Packit |
8a864e |
if (fd == INVALID_SOCKET)
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
HttpSocketStorageObject *p
|
|
Packit |
8a864e |
= new HttpSocketStorageObject(fd, mayRewind, hostStr);
|
|
Packit |
8a864e |
char locbuf[256] ;
|
|
Packit |
8a864e |
static String<char> nullStringC("", 0) ;
|
|
Packit |
8a864e |
char* line ;
|
|
Packit |
8a864e |
switch (p->open(host, port, path, mgr, locbuf)) {
|
|
Packit |
8a864e |
case HTTP_OK:
|
|
Packit |
8a864e |
return p ;
|
|
Packit |
8a864e |
case HTTP_REDIRECT:
|
|
Packit |
8a864e |
// (void)closesocket(fd);
|
|
Packit |
8a864e |
delete p ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// reassign host, port and path
|
|
Packit |
8a864e |
// and go round the loop again
|
|
Packit |
8a864e |
line = locbuf ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
if ( strdiff ("location:", line) )
|
|
Packit |
8a864e |
return 0 ;
|
|
Packit |
8a864e |
line += strlen("location:") ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
while ( isspace(*line) )
|
|
Packit |
8a864e |
++line ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// call ourself recursively with our new URL
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// construct message - there must be a better way even without
|
|
Packit |
8a864e |
// hacking on other source files
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
StringC sline ;
|
|
Packit |
8a864e |
for ( char* x = line; *x; ++x)
|
|
Packit |
8a864e |
sline += (Char)(*x) ;
|
|
Packit |
8a864e |
mgr.message(URLStorageMessages::Redirect, StringMessageArg(sline)) ;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
host = nullStringC ;
|
|
Packit |
8a864e |
path = nullStringC ;
|
|
Packit |
8a864e |
port = 0 ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
if ( strdiff ("http://", line) )
|
|
Packit |
8a864e |
return 0 ;
|
|
Packit |
8a864e |
line += strlen("http://") ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
while ( *line != ':' && *line != '/' )
|
|
Packit |
8a864e |
host += *line++ ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
if ( *line == ':' )
|
|
Packit |
8a864e |
while ( isdigit(*++line) )
|
|
Packit |
8a864e |
port = 10 * port + ( *line - '0' ) ;
|
|
Packit |
8a864e |
else
|
|
Packit |
8a864e |
port = 80 ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
while ( *line && ! isspace(*line) )
|
|
Packit |
8a864e |
path += *line++ ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
break ;
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
case HTTP_ERROR:
|
|
Packit |
8a864e |
delete p;
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
return 0 ; // we were in an infinite redirection loop
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#else /* not SP_HAVE_SOCKET */
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::notSupported);
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
#endif /* not SP_HAVE_SOCKET */
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean URLStorageManager::resolveRelative(const StringC &baseId,
|
|
Packit |
8a864e |
StringC &id,
|
|
Packit |
8a864e |
Boolean) const
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
static const char schemeChars[] =
|
|
Packit |
8a864e |
"abcdefghijklmnopqrstuvwxyz"
|
|
Packit |
8a864e |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
Packit |
8a864e |
"01234567879"
|
|
Packit |
8a864e |
"+-.";
|
|
Packit |
8a864e |
size_t i;
|
|
Packit |
8a864e |
// If it has a scheme, it is absolute.
|
|
Packit |
8a864e |
for (i = 0; i < id.size(); i++) {
|
|
Packit |
8a864e |
if (id[i] == ':') {
|
|
Packit |
8a864e |
if (i == 0)
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
else
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else if (!strchr(schemeChars, id[i]))
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
for (i = 0; i < id.size(); i++) {
|
|
Packit |
8a864e |
if (id[i] != '/')
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
size_t slashCount = i;
|
|
Packit |
8a864e |
if (slashCount > 0) {
|
|
Packit |
8a864e |
Boolean foundSameSlash = 0;
|
|
Packit |
8a864e |
size_t sameSlashPos;
|
|
Packit |
8a864e |
for (size_t j = 0; j < baseId.size(); j++) {
|
|
Packit |
8a864e |
size_t thisSlashCount = 0;
|
|
Packit |
8a864e |
for (size_t k = j; k < baseId.size() && baseId[k] == '/'; k++)
|
|
Packit |
8a864e |
thisSlashCount++;
|
|
Packit |
8a864e |
if (thisSlashCount == slashCount && !foundSameSlash) {
|
|
Packit |
8a864e |
foundSameSlash = 1;
|
|
Packit |
8a864e |
sameSlashPos = j;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else if (thisSlashCount > slashCount)
|
|
Packit |
8a864e |
foundSameSlash = 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (foundSameSlash) {
|
|
Packit |
8a864e |
StringC tem(baseId.data(), sameSlashPos);
|
|
Packit |
8a864e |
tem += id;
|
|
Packit |
8a864e |
tem.swap(id);
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else {
|
|
Packit |
8a864e |
size_t j;
|
|
Packit |
8a864e |
for (j = baseId.size(); j > 0; j--)
|
|
Packit |
8a864e |
if (baseId[j - 1] == '/')
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
if (j > 0) {
|
|
Packit |
8a864e |
StringC tem(baseId.data(), j);
|
|
Packit |
8a864e |
tem += id;
|
|
Packit |
8a864e |
tem.swap(id);
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
// FIXME remove xxx/../, and /.
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean URLStorageManager::transformNeutral(StringC &str, Boolean fold,
|
|
Packit |
8a864e |
Messenger &) const
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
if (fold)
|
|
Packit |
8a864e |
for (size_t i = 0; i < str.size(); i++) {
|
|
Packit |
8a864e |
Char c = str[i];
|
|
Packit |
8a864e |
if (c <= (unsigned char)-1)
|
|
Packit |
8a864e |
str[i] = tolower(str[i]);
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef SP_HAVE_SOCKET
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
SOCKET HttpSocketStorageObject::openHttp(const String<char> &theHost,
|
|
Packit |
8a864e |
unsigned short port,
|
|
Packit |
8a864e |
const StringC &hostStr,
|
|
Packit |
8a864e |
Messenger &mgr)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
String<char> host = theHost;
|
|
Packit |
8a864e |
host += '\0';
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef WINSOCK
|
|
Packit |
8a864e |
if (!winsockIniter.init(mgr))
|
|
Packit |
8a864e |
return INVALID_SOCKET;
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
struct sockaddr_in sock;
|
|
Packit |
8a864e |
sock.sin_family = AF_INET;
|
|
Packit |
8a864e |
sock.sin_port = htons(port);
|
|
Packit |
8a864e |
if (isdigit((unsigned char)host[0])) {
|
|
Packit |
8a864e |
unsigned long n = inet_addr(host.data());
|
|
Packit |
8a864e |
if (n == (unsigned long)-1) {
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::invalidHostNumber,
|
|
Packit |
8a864e |
StringMessageArg(hostStr));
|
|
Packit |
8a864e |
return INVALID_SOCKET;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
sock.sin_addr.s_addr = n;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else {
|
|
Packit |
8a864e |
struct hostent *hp = gethostbyname(host.data());
|
|
Packit |
8a864e |
if (!hp) {
|
|
Packit |
8a864e |
const MessageType1 *message;
|
|
Packit |
8a864e |
switch (h_errno) {
|
|
Packit |
8a864e |
case HOST_NOT_FOUND:
|
|
Packit |
8a864e |
message = &URLStorageMessages::hostNotFound;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
case TRY_AGAIN:
|
|
Packit |
8a864e |
message = &URLStorageMessages::hostTryAgain;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
case NO_RECOVERY:
|
|
Packit |
8a864e |
message = &URLStorageMessages::hostNoRecovery;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
case NO_DATA:
|
|
Packit |
8a864e |
#ifdef NO_ADDRESS
|
|
Packit |
8a864e |
#if NO_ADDRESS != NO_DATA
|
|
Packit |
8a864e |
case NO_ADDRESS:
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
message = &URLStorageMessages::hostNoData;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
default:
|
|
Packit |
8a864e |
#ifdef WINSOCK
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::hostOtherError,
|
|
Packit |
8a864e |
StringMessageArg(hostStr),
|
|
Packit |
8a864e |
WinsockMessageArg(h_errno));
|
|
Packit |
8a864e |
return INVALID_SOCKET;
|
|
Packit |
8a864e |
#else
|
|
Packit |
8a864e |
message = &URLStorageMessages::hostUnknownError;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
#endif
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(*message,
|
|
Packit |
8a864e |
StringMessageArg(hostStr));
|
|
Packit |
8a864e |
return INVALID_SOCKET;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
memcpy(&sock.sin_addr, hp->h_addr, hp->h_length);
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
SOCKET fd = socket(PF_INET, SOCK_STREAM, 0);
|
|
Packit |
8a864e |
if (fd == INVALID_SOCKET) {
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::cannotCreateSocket,
|
|
Packit |
8a864e |
SocketMessageArg(errnosocket));
|
|
Packit |
8a864e |
return INVALID_SOCKET;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (connect(fd, (struct sockaddr *)&sock, sizeof(sock)) == SOCKET_ERROR) {
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::cannotConnect,
|
|
Packit |
8a864e |
StringMessageArg(hostStr),
|
|
Packit |
8a864e |
SocketMessageArg(errnosocket));
|
|
Packit |
8a864e |
(void)closesocket(fd);
|
|
Packit |
8a864e |
return INVALID_SOCKET;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
return fd;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
HttpSocketStorageObject::HttpSocketStorageObject(SOCKET fd,
|
|
Packit |
8a864e |
Boolean mayRewind,
|
|
Packit |
8a864e |
const StringC &hostStr)
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
: RewindStorageObject(mayRewind, 0), hostStr_(hostStr), fd_(fd), eof_(0)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
HttpSocketStorageObject::~HttpSocketStorageObject()
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
if (fd_ != INVALID_SOCKET)
|
|
Packit |
8a864e |
(void)closesocket(fd_);
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
HTTP_RESPONSE_TYPE HttpSocketStorageObject::open(const String<char> &host,
|
|
Packit |
8a864e |
unsigned short port,
|
|
Packit |
8a864e |
const String<char> &path,
|
|
Packit |
8a864e |
Messenger &mgr,
|
|
Packit |
8a864e |
char locbuf[])
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
path_ = path;
|
|
Packit |
8a864e |
String<char> request;
|
|
Packit |
8a864e |
request.append("GET ", 4);
|
|
Packit |
8a864e |
request += path_;
|
|
Packit |
8a864e |
request += ' ';
|
|
Packit |
8a864e |
request.append("HTTP/1.0\r\n", 10);
|
|
Packit |
8a864e |
request.append("Host: ", 6);
|
|
Packit |
8a864e |
if (!isdigit((unsigned char)host[0])) {
|
|
Packit |
8a864e |
request += host;
|
|
Packit |
8a864e |
if (port != 80) {
|
|
Packit |
8a864e |
char portstr[sizeof(unsigned short)*3 + 1];
|
|
Packit |
8a864e |
sprintf(portstr, "%u", port);
|
|
Packit |
8a864e |
request.append(":", 1);
|
|
Packit |
8a864e |
request.append(portstr, strlen(portstr));
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
request.append("\r\n", 2);
|
|
Packit |
8a864e |
char* http_ua = getenv("SP_HTTP_USER_AGENT") ;
|
|
Packit |
8a864e |
if ( ! http_ua )
|
|
Packit |
8a864e |
http_ua = "libosp 1.5" ;
|
|
Packit |
8a864e |
request.append("User-Agent: ", 12) ;
|
|
Packit |
8a864e |
request.append(http_ua, strlen(http_ua)) ;
|
|
Packit |
8a864e |
request.append("\r\n", 2);
|
|
Packit |
8a864e |
const char* http_accept = getenv("SP_HTTP_ACCEPT") ;
|
|
Packit |
8a864e |
if ( http_accept ) {
|
|
Packit |
8a864e |
request.append("Accept: ", 8) ;
|
|
Packit |
8a864e |
request.append(http_accept, strlen(http_accept)) ;
|
|
Packit |
8a864e |
request.append("\r\n", 2);
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
request.append("\r\n", 2);
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// FIXME check length of write
|
|
Packit |
8a864e |
if (writesocket(fd_, request.data(), request.size()) == SOCKET_ERROR) {
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::writeError,
|
|
Packit |
8a864e |
StringMessageArg(hostStr_),
|
|
Packit |
8a864e |
SocketMessageArg(errnosocket));
|
|
Packit |
8a864e |
(void)closesocket(fd_);
|
|
Packit |
8a864e |
fd_ = INVALID_SOCKET;
|
|
Packit |
8a864e |
return HTTP_ERROR ;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
switch ( readHeader(mgr, locbuf) ) {
|
|
Packit |
8a864e |
case HTTP_OK:
|
|
Packit |
8a864e |
return HTTP_OK ;
|
|
Packit |
8a864e |
case HTTP_REDIRECT:
|
|
Packit |
8a864e |
(void)closesocket(fd_);
|
|
Packit |
8a864e |
return HTTP_REDIRECT ;
|
|
Packit |
8a864e |
case HTTP_ERROR:
|
|
Packit |
8a864e |
(void)closesocket(fd_);
|
|
Packit |
8a864e |
fd_ = INVALID_SOCKET;
|
|
Packit |
8a864e |
return HTTP_ERROR ;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
return HTTP_ERROR ;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
HTTP_RESPONSE_TYPE HttpSocketStorageObject::readHeader(Messenger &mgr,
|
|
Packit |
8a864e |
char locbuf[])
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
String<char> buf ;
|
|
Packit |
8a864e |
String<char> leftOver;
|
|
Packit |
8a864e |
if (!readLine(mgr, buf, leftOver))
|
|
Packit |
8a864e |
return HTTP_ERROR;
|
|
Packit |
8a864e |
buf += '\0';
|
|
Packit |
8a864e |
const char *ptr = &buf[0];
|
|
Packit |
8a864e |
int val;
|
|
Packit |
8a864e |
if (!parseStatus(ptr, val)) {
|
|
Packit |
8a864e |
if (buf.size() > 0)
|
|
Packit |
8a864e |
unread(buf.data(), buf.size() - 1);
|
|
Packit |
8a864e |
return HTTP_OK;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (val < 200 || val >= 400) {
|
|
Packit |
8a864e |
StringC reason;
|
|
Packit |
8a864e |
while (*ptr && *ptr != '\n' && *ptr != '\r') {
|
|
Packit |
8a864e |
reason += Char(*ptr);
|
|
Packit |
8a864e |
ptr++;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
StringC pathStr;
|
|
Packit |
8a864e |
for (size_t i = 0; i < path_.size(); i++)
|
|
Packit |
8a864e |
pathStr += path_[i];
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::getFailed,
|
|
Packit |
8a864e |
StringMessageArg(hostStr_),
|
|
Packit |
8a864e |
StringMessageArg(pathStr),
|
|
Packit |
8a864e |
StringMessageArg(reason));
|
|
Packit |
8a864e |
return HTTP_ERROR;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
for (;;) {
|
|
Packit |
8a864e |
if (!readLine(mgr, buf, leftOver))
|
|
Packit |
8a864e |
return HTTP_ERROR;
|
|
Packit |
8a864e |
if ( ! strdiff("location:", (char*) buf.data() ) ) {
|
|
Packit |
8a864e |
unsigned int sz = buf.size() > 255 ? 255 : buf.size() ;
|
|
Packit |
8a864e |
strncpy(locbuf, buf.data(), sz) ;
|
|
Packit |
8a864e |
locbuf[sz] = 0 ;
|
|
Packit |
8a864e |
for (int i=0; i
|
|
Packit |
8a864e |
if ( locbuf[i] == '\r' || locbuf[i] == '\n' ) {
|
|
Packit |
8a864e |
locbuf[i] = 0 ;
|
|
Packit |
8a864e |
break ;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (buf.size() == 0 || buf[0] == '\r' || buf[0] == '\n')
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (leftOver.size())
|
|
Packit |
8a864e |
unread(leftOver.data(), leftOver.size());
|
|
Packit |
8a864e |
return ( val < 300 ) ? HTTP_OK : HTTP_REDIRECT ;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// Status line must start with: "HTTP/" 1*DIGIT "." 1*DIGIT SP 3DIGIT SP
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean HttpSocketStorageObject::parseStatus(const char *&ptr, int &val)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
static const char ver[] = "HTTP/";
|
|
Packit |
8a864e |
for (const char *v = ver; *v; v++, ptr++)
|
|
Packit |
8a864e |
if (*v != *ptr)
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
if (!isdigit((unsigned char)*ptr))
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
do {
|
|
Packit |
8a864e |
++ptr;
|
|
Packit |
8a864e |
} while (isdigit((unsigned char)*ptr));
|
|
Packit |
8a864e |
if (*ptr != '.')
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
ptr++;
|
|
Packit |
8a864e |
if (!isdigit((unsigned char)*ptr))
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
do {
|
|
Packit |
8a864e |
++ptr;
|
|
Packit |
8a864e |
} while (isdigit((unsigned char)*ptr));
|
|
Packit |
8a864e |
if (*ptr != ' ')
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
ptr++;
|
|
Packit |
8a864e |
val = 0;
|
|
Packit |
8a864e |
for (int i = 0; i < 3; i++, ptr++) {
|
|
Packit |
8a864e |
if (!isdigit((unsigned char)*ptr))
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
val = val*10 + *ptr - '0';
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (*ptr != ' ')
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
ptr++;
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
// True will be returned for an empty line.
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean HttpSocketStorageObject::readLine(Messenger &mgr,
|
|
Packit |
8a864e |
String<char> &line,
|
|
Packit |
8a864e |
String<char> &leftOver)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
line.resize(0);
|
|
Packit |
8a864e |
Boolean hadCr = 0;
|
|
Packit |
8a864e |
Boolean gotLine = 0;
|
|
Packit |
8a864e |
size_t li;
|
|
Packit |
8a864e |
for (li = 0; li < leftOver.size(); li++) {
|
|
Packit |
8a864e |
if (leftOver[li] == '\r') {
|
|
Packit |
8a864e |
if (hadCr) {
|
|
Packit |
8a864e |
gotLine = 1;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
line += '\r';
|
|
Packit |
8a864e |
hadCr = 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else if (leftOver[li] == '\n') {
|
|
Packit |
8a864e |
line += '\n';
|
|
Packit |
8a864e |
li++;
|
|
Packit |
8a864e |
gotLine = 1;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else if (hadCr) {
|
|
Packit |
8a864e |
gotLine = 1;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else
|
|
Packit |
8a864e |
line += leftOver[li];
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (gotLine) {
|
|
Packit |
8a864e |
for (size_t i = li; i < leftOver.size(); i++)
|
|
Packit |
8a864e |
leftOver[i - li] = leftOver[i];
|
|
Packit |
8a864e |
leftOver.resize(leftOver.size() - li);
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
leftOver.resize(0);
|
|
Packit |
8a864e |
if (eof_)
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
for (;;) {
|
|
Packit |
8a864e |
char c;
|
|
Packit |
8a864e |
long n;
|
|
Packit |
8a864e |
do {
|
|
Packit |
8a864e |
n = readsocket(fd_, &c, 1);
|
|
Packit |
8a864e |
} while (n < 0 && errnosocket == SOCKET_EINTR);
|
|
Packit |
8a864e |
if (n == 0) {
|
|
Packit |
8a864e |
(void)closesocket(fd_);
|
|
Packit |
8a864e |
eof_ = 1;
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (n < 0) {
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::readError,
|
|
Packit |
8a864e |
StringMessageArg(hostStr_),
|
|
Packit |
8a864e |
SocketMessageArg(errnosocket));
|
|
Packit |
8a864e |
(void)closesocket(fd_);
|
|
Packit |
8a864e |
fd_ = INVALID_SOCKET;
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
switch (c) {
|
|
Packit |
8a864e |
case '\r':
|
|
Packit |
8a864e |
if (hadCr) {
|
|
Packit |
8a864e |
leftOver += c;
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
hadCr = 1;
|
|
Packit |
8a864e |
line += c;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
case '\n':
|
|
Packit |
8a864e |
line += c;
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
default:
|
|
Packit |
8a864e |
if (hadCr) {
|
|
Packit |
8a864e |
leftOver += c;
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
line += c;
|
|
Packit |
8a864e |
break;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
return 0; // not reached
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean HttpSocketStorageObject::read(char *buf, size_t bufSize, Messenger &mgr,
|
|
Packit |
8a864e |
size_t &nread)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
if (readSaved(buf, bufSize, nread))
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
if (fd_ == INVALID_SOCKET || eof_)
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
long n;
|
|
Packit |
8a864e |
do {
|
|
Packit |
8a864e |
n = readsocket(fd_, buf, bufSize);
|
|
Packit |
8a864e |
} while (n < 0 && errnosocket == SOCKET_EINTR);
|
|
Packit |
8a864e |
if (n > 0) {
|
|
Packit |
8a864e |
nread = size_t(n);
|
|
Packit |
8a864e |
saveBytes(buf, nread);
|
|
Packit |
8a864e |
return 1;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
if (n < 0) {
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::readError,
|
|
Packit |
8a864e |
StringMessageArg(hostStr_),
|
|
Packit |
8a864e |
SocketMessageArg(errnosocket));
|
|
Packit |
8a864e |
fd_ = INVALID_SOCKET;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
else {
|
|
Packit |
8a864e |
eof_ = 1;
|
|
Packit |
8a864e |
if (closesocket(fd_) == SOCKET_ERROR)
|
|
Packit |
8a864e |
ParentLocationMessenger(mgr).message(URLStorageMessages::closeError,
|
|
Packit |
8a864e |
StringMessageArg(hostStr_),
|
|
Packit |
8a864e |
SocketMessageArg(errnosocket));
|
|
Packit |
8a864e |
fd_ = INVALID_SOCKET;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
Boolean HttpSocketStorageObject::seekToStart(Messenger &)
|
|
Packit |
8a864e |
{
|
|
Packit |
8a864e |
CANNOT_HAPPEN();
|
|
Packit |
8a864e |
return 0;
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#endif /* SP_HAVE_SOCKET */
|
|
Packit |
8a864e |
|
|
Packit |
8a864e |
#ifdef SP_NAMESPACE
|
|
Packit |
8a864e |
}
|
|
Packit |
8a864e |
#endif
|