19 # include <vcl_msvc_warnings.h> 24 #if defined (_WIN32) && !defined(__CYGWIN__) 25 # include <winsock2.h> 29 # include <sys/socket.h> 30 # include <netinet/in.h> 34 #if defined(_WIN32) && !defined(__CYGWIN__) 36 static int called_WSAStartup = 0;
49 assert (std::strncmp(url,
"http://", 7) == 0);
51 char const *p = url + 7;
54 host = std::string(url+7, p);
63 for (
unsigned int i=0; i<host.size(); ++i)
65 auth = std::string(host.c_str(), host.c_str()+i);
66 host = std::string(host.c_str()+i+1, host.c_str() + host.size());
72 for (
unsigned int i=(
unsigned int)(host.size()-1); i>0; --i)
74 port = std::atoi(host.c_str() + i + 1);
75 host = std::string(host.c_str(), host.c_str() + i);
81 while (k < path.size())
84 path.replace(k, 1,
"%20");
85 else if (path[k] ==
'%')
86 path.replace(k, 1,
"%25");
92 std::cerr <<
"auth = \'" << auth <<
"\'\n" 93 <<
"host = \'" << host <<
"\'\n" 94 <<
"path = \'" << path <<
"\'\n" 95 <<
"port = " << port << std::endl;
98 #if defined(_WIN32) && !defined(__CYGWIN__) 99 if (called_WSAStartup==0)
101 WORD wVersionRequested;
104 wVersionRequested = MAKEWORD( 2, 2 );
106 WSAStartup( wVersionRequested, &wsaData );
111 SOCKET tcp_socket = socket(PF_INET,
115 #if defined(_WIN32) && !defined(__CYGWIN__) 116 if (tcp_socket == INVALID_SOCKET) {
118 std::cerr << __FILE__
"error code : " << WSAGetLastError() <<
'\n';
121 if (tcp_socket < 0) {
123 std::cerr << __FILE__
": failed to create socket.\n";
128 std::cerr << __FILE__
": tcp_socket = " << tcp_socket <<
'\n';
132 hostent *hp = gethostbyname(host.c_str());
134 std::cerr << __FILE__
": failed to lookup host\n";
136 #if defined(_WIN32) && !defined(__CYGWIN__) 137 closesocket(tcp_socket);
147 my_addr.sin_family = AF_INET;
149 my_addr.sin_port = htons(port);
150 std::memcpy(&my_addr.sin_addr, hp->h_addr_list[0], hp->h_length);
153 if (connect(tcp_socket , (sockaddr *) &my_addr,
sizeof my_addr) < 0) {
154 std::cerr << __FILE__
": failed to connect to host\n";
157 #if defined(_WIN32) && !defined(__CYGWIN__) 158 closesocket(tcp_socket);
170 std::snprintf(buffer, 4090-std::strlen(buffer),
171 "GET %s HTTP/1.1\r\nUser-Agent: vul_url\r\nHost: %s\r\nAccept: */*\r\n",
175 std::snprintf(buffer+std::strlen(buffer), 4090-std::strlen(buffer),
176 "Authorization: Basic %s\r\n",
179 if (std::snprintf(buffer+std::strlen(buffer), 4090-std::strlen(buffer),
"\r\n") < 0)
181 std::cerr <<
"ERROR: vul_http_open buffer overflow.";
185 #if defined(_WIN32) && !defined(__CYGWIN__) 186 if (send(tcp_socket, buffer, (
int)std::strlen(buffer), 0) < 0) {
188 if (::write(tcp_socket, buffer, std::strlen(buffer)) < 0) {
190 std::cerr << __FILE__
": error sending HTTP request\n";
192 #if defined(_WIN32) && !defined(__CYGWIN__) 193 closesocket(tcp_socket);
202 std::string contents;
205 #if defined(_WIN32) && !defined(__CYGWIN__) 206 while ((n = recv(tcp_socket, buffer,
sizeof buffer,0 )) > 0) {
208 while ((n = ::read(tcp_socket, buffer,
sizeof buffer)) > 0) {
210 contents.append(buffer, n);
212 std::cerr << n <<
" bytes\n";
218 #if defined(_WIN32) && !defined(__CYGWIN__) 219 closesocket(tcp_socket);
225 std::cerr <<
"HTTP server returned:\n" << contents <<
'\n';
228 if (contents.find(
"HTTP/1.1 200") == contents.npos)
232 std::string::size_type n = contents.find(
"\r\n\r\n");
233 if (n == contents.npos)
238 contents.erase(0,n+4);
240 std::cerr <<
"vul_url::vul_http_open() returns:\n" << contents <<
'\n';
242 return new std::istringstream(contents);
254 assert (std::strncmp(url,
"http://", 7) == 0);
256 char const *p = url + 7;
257 while (*p && *p!=
'/')
259 host = std::string(url+7, p);
268 for (
unsigned int i=0; i<host.size(); ++i)
269 if (host[i] ==
'@') {
270 auth = std::string(host.c_str(), host.c_str()+i);
271 host = std::string(host.c_str()+i+1, host.c_str() + host.size());
276 for (
unsigned int i=0; i<host.size(); ++i)
277 if (host[i] ==
':') {
278 port = std::atoi(host.c_str() + i + 1);
279 host = std::string(host.c_str(), host.c_str() + i);
285 while (k < path.size())
288 path.replace(k, 1,
"%20");
289 else if (path[k] ==
'%')
290 path.replace(k, 1,
"%25");
296 std::cerr <<
"auth = \'" << auth <<
"\'\n" 297 <<
"host = \'" << host <<
"\'\n" 298 <<
"path = \'" << path <<
"\'\n" 299 <<
"port = " << port << std::endl;
302 #if defined(_WIN32) && !defined(__CYGWIN__) 303 if (called_WSAStartup==0)
305 WORD wVersionRequested;
308 wVersionRequested = MAKEWORD( 2, 2 );
310 WSAStartup( wVersionRequested, &wsaData );
315 SOCKET tcp_socket = socket(PF_INET,
320 #if defined(_WIN32) && !defined(__CYGWIN__) 321 if (tcp_socket == INVALID_SOCKET) {
323 std::cerr <<
"error code : " << WSAGetLastError() << std::endl;
326 if (tcp_socket < 0) {
328 std::cerr << __FILE__
": failed to create socket.\n";
333 std::cerr << __FILE__
": tcp_socket = " << tcp_socket << std::endl;
337 hostent *hp = gethostbyname(host.c_str());
339 std::cerr << __FILE__
": failed to lookup host\n";
345 my_addr.sin_family = AF_INET;
347 my_addr.sin_port = htons(port);
348 std::memcpy(&my_addr.sin_addr, hp->h_addr_list[0], hp->h_length);
351 if (connect(tcp_socket , (sockaddr *) &my_addr,
sizeof my_addr) < 0)
353 std::cerr << __FILE__
": failed to connect to host\n";
355 #if defined(_WIN32) && !defined(__CYGWIN__) 356 closesocket(tcp_socket);
368 std::snprintf(buffer, 4090,
369 "HEAD %s HTTP/1.1\r\nUser-Agent: vul_url\r\nHost: %s\r\nAccept: */*\r\n",
372 std::snprintf(buffer+std::strlen(buffer), 4090-std::strlen(buffer),
373 "Authorization: Basic %s\r\n",
376 if (std::snprintf(buffer+std::strlen(buffer), 4090-std::strlen(buffer),
"\r\n") < 0)
378 std::cerr <<
"ERROR: vul_http_exists buffer overflow.";
382 #if defined(_WIN32) && !defined(__CYGWIN__) 383 if (send(tcp_socket, buffer, (
int)std::strlen(buffer), 0) < 0) {
385 if (::write(tcp_socket, buffer, std::strlen(buffer)) < 0) {
387 std::cerr << __FILE__
": error sending HTTP request\n";
389 #if defined(_WIN32) && !defined(__CYGWIN__) 390 closesocket(tcp_socket);
399 std::string contents;
402 #if defined(_WIN32) && !defined(__CYGWIN__) 403 if ((n = recv(tcp_socket, buffer,
sizeof buffer,0 )) > 0) {
405 if ((n = ::read(tcp_socket, buffer,
sizeof buffer)) > 0) {
407 contents.append(buffer, n);
412 #if defined(_WIN32) && !defined(__CYGWIN__) 413 closesocket(tcp_socket);
422 #if defined(_WIN32) && !defined(__CYGWIN__) 423 closesocket(tcp_socket);
429 std::cerr <<
"HTTP server returned:\n" << contents <<
'\n';
432 return contents.find(
"HTTP/1.1 200") != contents.npos;
441 unsigned int l = (
unsigned int)std::strlen(url);
444 if (l > 7 && std::strncmp(url,
"file://", 7) == 0)
445 return new std::ifstream(url+7,mode);
448 if (l > 7 && std::strncmp(url,
"http://", 7) == 0)
452 if (l > 6 && std::strncmp(url,
"ftp://", 6) == 0)
454 std::cerr << __LINE__ <<
"ERROR:\n vul_read_url(const char * url)\n" 455 "Doesn't support FTP yet, url=" << url << std::endl;
460 return new std::ifstream(url, mode);
470 unsigned int l = (
unsigned int)std::strlen(url);
473 if (l > 7 && std::strncmp(url,
"file://", 7) == 0)
477 if (l > 7 && std::strncmp(url,
"http://", 7) == 0)
481 if (l > 6 && std::strncmp(url,
"ftp://", 6) == 0)
483 std::cerr <<
"ERROR: vul_read_url(const char * url)\n" 484 "Doesn't support FTP yet, url=" << url << std::endl;
498 unsigned int l = (
unsigned int)std::strlen(url);
501 if (l > 7 && std::strncmp(url,
"file://", 7) == 0)
505 if (l > 7 && std::strncmp(url,
"http://", 7) == 0)
509 if (l > 8 && std::strncmp(url,
"https://", 7) == 0)
513 if (l > 6 && std::strncmp(url,
"ftp://", 6) == 0)
532 char base64_encoding[]=
534 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
535 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
536 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
537 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/' 540 static char out_buf[4];
542 static const char * encode_triplet(
char data[3],
unsigned int n)
544 assert (n>0 && n <4);
545 out_buf[0] = base64_encoding[(data[0] & 0xFC) >> 2];
546 out_buf[1] = base64_encoding[
547 ((data[0] & 0x3) << 4) + ((data[1] & 0xf0)>>4)];
551 out_buf[2] = out_buf[3] =
'=';
555 out_buf[2] = base64_encoding[
556 ((data[1] & 0xf) << 2) + ((data[2] & 0xc0)>>6)];
564 out_buf[3] = base64_encoding[ (data[2] & 0x3f) ];
573 unsigned int i = 0, line_octets = 0;
574 const unsigned int l = (
unsigned int)(in.size());
585 data[1] = data[2] = 0;
589 out.append(encode_triplet(data,1),4);
597 out.append(encode_triplet(data,2),4);
603 out.append(encode_triplet(data,3),4);
605 if (line_octets >= 68/4)
607 out.append(
"\r\n",2);
619 static int get_next_char(
const std::string &in,
unsigned int *i)
621 while (*i < in.size())
632 if (c >=
'A' && c <=
'Z')
633 return 0 + (int)c - (
int)
'A';
635 if (c >=
'a' && c <=
'z')
636 return 26 + (int)c - (
int)
'a';
638 if (c >=
'0' && c <=
'9')
639 return 52 + (int)c - (
int)
'0';
655 const unsigned int l = (
unsigned int)(in.size());
659 data[0] = data[1] = data[2] = 0;
663 c = get_next_char(in , &i);
671 data[0] = char(((c & 0x3f) << 2) | (0x3 & data[0]));
675 c = get_next_char(in , &i);
678 if (c == 64 || c==-1)
681 data[0] = char(((c & 0x30) >> 4) | (0xfc & data[0]));
682 data[1] = char(((c & 0x0f) << 4) | (0x0f & data[1]));
687 c = get_next_char(in , &i);
698 data[1] = char(((c & 0x3c) >> 2) | (0xf0 & data[1]));
699 data[2] = char(((c & 0x03) << 6) | (0x3f & data[2]));
703 c = get_next_char(in , &i);
714 data[2] = char((c & 0x3f) | (0xc0 & data[2]));
static std::string encode_base64(const std::string &in)
Encode a string of chars into base64 format.
static bool is_file(const char *url)
Is that a file.
A collection of miscellaneous filesystem-type utilities.
static bool exists(const char *url)
Does that URL exist.
static bool is_directory(char const *filename)
Return true iff filename is a directory.
std::istream * vul_http_open(char const *url)
only call this method with a correctly formatted http URL.
static std::istream * open(const char *url, std::ios::openmode mode=std::ios::in)
open a URL.
static bool is_url(const char *url)
Is that a URL.
bool vul_http_exists(char const *url)
only call this method with a correctly formatted http URL.
static std::string decode_base64(const std::string &in)
Decode a string of chars from base64 format.
Static class methods to test and open streams via a URL.
static bool exists(char const *filename)
Return true iff filename exists. It may be any sort of file.