18 # include <vcl_msvc_warnings.h> 21 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 25 # include <sys/socket.h> 26 # include <netinet/in.h> 28 #elif defined (_WIN32) && !defined(__CYGWIN__) 29 # include <winsock2.h> 34 char base64_encoding[]=
36 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
37 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
38 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
39 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/' 42 static char out_buf[4];
44 static const char * encode_triplet(
const char data[3],
unsigned n)
47 out_buf[0] = base64_encoding[(data[0] & 0xFC) >> 2];
51 out_buf[2] = out_buf[3] =
'=';
55 out_buf[1] = base64_encoding[
56 ((data[0] & 0x3) << 4) + ((data[1] & 0xf0)>>4)];
57 out_buf[2] = base64_encoding[
58 ((data[1] & 0xf) << 2) + ((data[2] & 0xc0)>>6)];
66 out_buf[3] = base64_encoding[ (data[2] & 0x3f) ];
72 static std::string encode_base64(
const std::string& in)
75 unsigned int i = 0, line_octets = 0;
76 const auto l = (
unsigned int)(in.size());
81 data[1] = data[2] = 0;
85 out.append(encode_triplet(data,1),4);
93 out.append(encode_triplet(data,2),4);
99 out.append(encode_triplet(data,3),4);
101 if (line_octets >= 68/4)
103 out.append(
"\r\n",2);
117 if (std::strncmp(url,
"http://", 7) != 0)
120 char const *p = url+7;
121 while (*p && *p!=
'/')
125 std::string host = std::string(url+7, p);
126 std::string path = (*p) ? p+1 :
"";
131 for (
unsigned int i=0; i<host.size(); ++i)
132 if (host[i] ==
'@') {
133 auth = std::string(host.c_str(), host.c_str()+i);
134 host = std::string(host.c_str()+i+1, host.c_str() + host.size());
140 for (
auto i=(
unsigned int)(host.size()-1); i>0; --i)
141 if (host[i] ==
':') {
142 port = std::atoi(host.c_str() + i + 1);
143 host = std::string(host.c_str(), host.c_str() + i);
148 for (
unsigned k =0; k < path.size(); ++k)
150 path.replace(k, 1,
"%20");
151 else if (path[k] ==
'%')
152 path.replace(k, 1,
"%25");
156 std::cerr <<
"auth = \'" << auth <<
"\'\n" 157 <<
"host = \'" << host <<
"\'\n" 158 <<
"path = \'" << path <<
"\'\n" 159 <<
"port = " << port << std::endl;
162 #if defined(_WIN32) && !defined(__CYGWIN__) 163 static int called_WSAStartup;
164 if (called_WSAStartup==0)
166 WORD wVersionRequested;
169 wVersionRequested = MAKEWORD( 2, 2 );
171 WSAStartup( wVersionRequested, &wsaData );
176 SOCKET tcp_socket = socket(PF_INET,
180 #if defined(_WIN32) && !defined(__CYGWIN__) 181 if (tcp_socket == INVALID_SOCKET) {
182 std::cerr << __FILE__
": failed to create socket.\n";
184 std::cerr <<
"error code : " << WSAGetLastError() << std::endl;
190 std::cerr << __FILE__
": failed to create socket.\n";
194 std::cerr << __FILE__
": tcp_sockect = " << tcp_socket << std::endl;
198 hostent *hp = gethostbyname(host.c_str());
200 std::cerr << __FILE__
": failed to lookup host\n";
201 #if defined(_WIN32) && !defined(__CYGWIN__) 202 closesocket(tcp_socket);
211 my_addr.sin_family = AF_INET;
212 my_addr.sin_port = htons(port);
213 std::memcpy(&my_addr.sin_addr, hp->h_addr_list[0], hp->h_length);
216 if (connect(tcp_socket , (sockaddr *) &my_addr,
sizeof my_addr) < 0) {
217 std::cerr << __FILE__
": failed to connect to host\n";
219 #if defined(_WIN32) && !defined(__CYGWIN__) 220 closesocket(tcp_socket);
232 std::snprintf(buffer, 4090,
"GET /%s / HTTP/1.1\r\n", path.c_str());
234 std::snprintf(buffer+std::strlen(buffer), 4090-std::strlen(buffer),
235 "Authorization: Basic %s\n", encode_base64(auth).c_str());
237 if (std::snprintf(buffer+std::strlen(buffer), 4090-std::strlen(buffer),
"\r\n") < 0)
239 std::cerr <<
"ERROR: vil_stream_url buffer overflow.";
243 #if defined(_WIN32) && !defined(__CYGWIN__) 244 if (send(tcp_socket, buffer, (
int)std::strlen(buffer), 0) < 0)
246 std::cerr << __FILE__
": error sending HTTP request\n";
247 closesocket(tcp_socket);
251 if (::
write(tcp_socket, buffer, std::strlen(buffer)) < 0)
253 std::cerr << __FILE__
": error sending HTTP request\n";
266 unsigned entity_marker = 0;
268 #if defined(_WIN32) && !defined(__CYGWIN__) 269 while ((n = recv(tcp_socket, buffer,
sizeof buffer,0 )) > 0L)
271 while ((n = ::
read(tcp_socket, buffer,
sizeof buffer)) > 0L)
276 assert (entity_marker < 5);
277 if (entity_marker==4)
286 if ((entity_marker==2||entity_marker==0) && buffer[i]==
'\r') entity_marker++;
287 else if (entity_marker==1 && buffer[i]==
'\n') entity_marker++;
288 else if (entity_marker==3 && buffer[i]==
'\n')
295 else entity_marker=0;
301 #if 0 // useful for figuring out where the error is 303 std::ofstream test(
"/test.jpg", std::ios::binary);
306 test.write(btest, bn);
312 #if defined(_WIN32) && !defined(__CYGWIN__) 313 closesocket(tcp_socket);
vil_stream_url(vil_stream_url const &)
virtual vil_streampos write(void const *buf, vil_streampos n)=0
Write n bytes from buf. Returns number of bytes written.
vil_streampos read(void *buf, vil_streampos n) override
Read n bytes into buf. Returns number of bytes read.
virtual void seek(vil_streampos position)=0
Goto file pointer.
virtual vil_streampos read(void *buf, vil_streampos n)=0
Read n bytes into buf. Returns number of bytes read.
void ref()
up/down the reference count.
~vil_stream_url() override
An in-core vil_stream implementation.
An in-core vil_stream implementation.
vil_streampos write(void const *buf, vil_streampos n) override
Write n bytes from buf. Returns number of bytes written.