1
/* $Id: url.c,v 1.89 2004/04/16 18:47:19 ukai Exp $ */
4
#include <sys/socket.h>
5
#include <netinet/in.h>
15
#include <io.h> /* ?? */
24
#ifndef SSLEAY_VERSION_NUMBER
25
#include <openssl/crypto.h> /* SSLEAY_VERSION_NUMBER may be here */
27
#include <openssl/err.h>
31
#define write(a,b,c) write_s(a,b,c)
32
#endif /* __WATT32__ */
35
/* see rc.c, "dns_order" and dnsorders[] */
36
int ai_family_order_table[7][3] = {
37
{PF_UNSPEC, PF_UNSPEC, PF_UNSPEC}, /* 0:unspec */
38
{PF_INET, PF_INET6, PF_UNSPEC}, /* 1:inet inet6 */
39
{PF_INET6, PF_INET, PF_UNSPEC}, /* 2:inet6 inet */
40
{PF_UNSPEC, PF_UNSPEC, PF_UNSPEC}, /* 3: --- */
41
{PF_INET, PF_UNSPEC, PF_UNSPEC}, /* 4:inet */
42
{PF_UNSPEC, PF_UNSPEC, PF_UNSPEC}, /* 5: --- */
43
{PF_INET6, PF_UNSPEC, PF_UNSPEC}, /* 6:inet6 */
47
static JMP_BUF AbortLoading;
49
/* XXX: note html.h SCM_ */
56
0, /* local - not defined */
57
0, /* local-CGI - not defined? */
58
0, /* exec - not defined? */
63
0, /* data - not defined */
64
0, /* mailto - not defined */
70
struct cmdtable schemetable[] = {
72
{"gopher", SCM_GOPHER},
76
/* {"exec", SCM_EXEC}, */
78
/* {"nntp", SCM_NNTP_GROUP}, */
80
/* {"news", SCM_NEWS_GROUP}, */
83
{"mailto", SCM_MAILTO},
91
static struct table2 DefaultGuess[] = {
92
{"html", "text/html"},
94
{"shtml", "text/html"},
96
{"jpeg", "image/jpeg"},
97
{"jpg", "image/jpeg"},
100
{"au", "audio/basic"},
101
{"gz", "application/x-gzip"},
102
{"Z", "application/x-compress"},
103
{"bz2", "application/x-bzip"},
104
{"tar", "application/x-tar"},
105
{"zip", "application/x-zip"},
106
{"lha", "application/x-lha"},
107
{"lzh", "application/x-lha"},
108
{"ps", "application/postscript"},
109
{"pdf", "application/pdf"},
113
static void add_index_file(ParsedURL *pu, URLFile *uf);
115
/* #define HTTP_DEFAULT_FILE "/index.html" */
117
#ifndef HTTP_DEFAULT_FILE
118
#define HTTP_DEFAULT_FILE "/"
119
#endif /* not HTTP_DEFAULT_FILE */
125
sock_log(char *message, ...)
127
FILE *f = fopen("zzzsocklog", "a");
132
va_start(va, message);
133
vfprintf(f, message, va);
139
static TextList *mimetypes_list;
140
static struct table2 **UserMimeTypes;
142
static struct table2 *
143
loadMimeTypes(char *filename)
149
struct table2 *mtypes;
151
f = fopen(expandPath(filename), "r");
155
while (tmp = Strfgets(f), tmp->length > 0) {
158
d = strtok(d, " \t\n\r");
160
d = strtok(NULL, " \t\n\r");
161
for (i = 0; d != NULL; i++)
162
d = strtok(NULL, " \t\n\r");
168
mtypes = New_N(struct table2, n + 1);
170
while (tmp = Strfgets(f), tmp->length > 0) {
174
type = strtok(d, " \t\n\r");
178
d = strtok(NULL, " \t\n\r");
181
mtypes[i].item1 = Strnew_charp(d)->ptr;
182
mtypes[i].item2 = Strnew_charp(type)->ptr;
186
mtypes[i].item1 = NULL;
187
mtypes[i].item2 = NULL;
198
if (non_null(mimetypes_files))
199
mimetypes_list = make_domain_list(mimetypes_files);
201
mimetypes_list = NULL;
202
if (mimetypes_list == NULL)
204
UserMimeTypes = New_N(struct table2 *, mimetypes_list->nitem);
205
for (i = 0, tl = mimetypes_list->first; tl; i++, tl = tl->next)
206
UserMimeTypes[i] = loadMimeTypes(tl->ptr);
210
DefaultFile(int scheme)
217
return allocStr(HTTP_DEFAULT_FILE, -1);
220
return allocStr("1", -1);
221
#endif /* USE_GOPHER */
226
return allocStr("/", -1);
231
static MySignalHandler
234
LONGJMP(AbortLoading, 1);
239
SSL_CTX *ssl_ctx = NULL;
245
SSL_CTX_free(ssl_ctx);
247
ssl_accept_this_site(NULL);
250
#if SSLEAY_VERSION_NUMBER >= 0x00905100
251
#include <openssl/rand.h>
260
if ((file = RAND_file_name(buffer, sizeof(buffer)))) {
262
if (RAND_egd(file) > 0)
265
RAND_load_file(file, -1);
269
srand48((long)time(NULL));
270
while (!RAND_status()) {
272
RAND_seed((unsigned char *)&l, sizeof(long));
276
RAND_write_file(file);
278
#endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
281
openSSLHandle(int sock, char *hostname, char **p_cert)
284
static char *old_ssl_forbid_method = NULL;
285
#ifdef USE_SSL_VERIFY
286
static int old_ssl_verify_server = -1;
289
if (old_ssl_forbid_method != ssl_forbid_method
290
&& (!old_ssl_forbid_method || !ssl_forbid_method ||
291
strcmp(old_ssl_forbid_method, ssl_forbid_method))) {
292
old_ssl_forbid_method = ssl_forbid_method;
293
#ifdef USE_SSL_VERIFY
294
ssl_path_modified = 1;
299
#ifdef USE_SSL_VERIFY
300
if (old_ssl_verify_server != ssl_verify_server) {
301
old_ssl_verify_server = ssl_verify_server;
302
ssl_path_modified = 1;
304
if (ssl_path_modified) {
306
ssl_path_modified = 0;
308
#endif /* defined(USE_SSL_VERIFY) */
309
if (ssl_ctx == NULL) {
311
#if SSLEAY_VERSION_NUMBER < 0x0800
312
ssl_ctx = SSL_CTX_new();
313
X509_set_default_verify_paths(ssl_ctx->cert);
314
#else /* SSLEAY_VERSION_NUMBER >= 0x0800 */
315
SSLeay_add_ssl_algorithms();
316
SSL_load_error_strings();
317
if (!(ssl_ctx = SSL_CTX_new(SSLv23_client_method())))
320
if (ssl_forbid_method) {
321
if (strchr(ssl_forbid_method, '2'))
322
option |= SSL_OP_NO_SSLv2;
323
if (strchr(ssl_forbid_method, '3'))
324
option |= SSL_OP_NO_SSLv3;
325
if (strchr(ssl_forbid_method, 't'))
326
option |= SSL_OP_NO_TLSv1;
327
if (strchr(ssl_forbid_method, 'T'))
328
option |= SSL_OP_NO_TLSv1;
330
SSL_CTX_set_options(ssl_ctx, option);
331
#ifdef USE_SSL_VERIFY
332
/* derived from openssl-0.9.5/apps/s_{client,cb}.c */
333
#if 1 /* use SSL_get_verify_result() to verify cert */
334
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
336
SSL_CTX_set_verify(ssl_ctx,
337
ssl_verify_server ? SSL_VERIFY_PEER :
338
SSL_VERIFY_NONE, NULL);
340
if (ssl_cert_file != NULL && *ssl_cert_file != '\0') {
342
if (SSL_CTX_use_certificate_file
343
(ssl_ctx, ssl_cert_file, SSL_FILETYPE_PEM) > 0) {
344
char *key_file = (ssl_key_file == NULL
346
'\0') ? ssl_cert_file : ssl_key_file;
347
if (SSL_CTX_use_PrivateKey_file
348
(ssl_ctx, key_file, SSL_FILETYPE_PEM) > 0)
349
if (SSL_CTX_check_private_key(ssl_ctx))
357
if ((!ssl_ca_file && !ssl_ca_path)
358
|| SSL_CTX_load_verify_locations(ssl_ctx, ssl_ca_file, ssl_ca_path))
359
#endif /* defined(USE_SSL_VERIFY) */
360
SSL_CTX_set_default_verify_paths(ssl_ctx);
361
#endif /* SSLEAY_VERSION_NUMBER >= 0x0800 */
363
handle = SSL_new(ssl_ctx);
364
SSL_set_fd(handle, sock);
365
#if SSLEAY_VERSION_NUMBER >= 0x00905100
367
#endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
368
if (SSL_connect(handle) > 0) {
369
Str serv_cert = ssl_get_certificate(handle, hostname);
371
*p_cert = serv_cert->ptr;
382
/* FIXME: gettextize? */
383
disp_err_message(Sprintf
385
ERR_error_string(ERR_get_error(), NULL))->ptr, FALSE);
390
SSL_write_from_file(SSL * ssl, char *file)
395
fd = fopen(file, "r");
397
while ((c = fgetc(fd)) != EOF) {
399
SSL_write(ssl, buf, 1);
408
write_from_file(int sock, char *file)
413
fd = fopen(file, "r");
415
while ((c = fgetc(fd)) != EOF) {
426
if (buf->bufferprop & BP_NO_URL) {
427
/* no URL is defined for the buffer */
430
if (buf->baseURL != NULL) {
431
/* <BASE> tag is defined in the document */
435
return &buf->currentURL;
439
openSocket(char *const hostname,
440
char *remoteport_name, unsigned short remoteport_num)
442
volatile int sock = -1;
445
struct addrinfo hints, *res0, *res;
448
#else /* not INET6 */
449
struct sockaddr_in hostaddr;
450
struct hostent *entry;
451
struct protoent *proto;
452
unsigned short s_port;
455
#endif /* not INET6 */
456
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
459
/* FIXME: gettextize? */
460
message(Sprintf("Opening socket...")->ptr, 0, 0);
463
if (SETJMP(AbortLoading) != 0) {
465
sock_log("openSocket() failed. reason: user abort\n");
472
if (hostname == NULL) {
474
sock_log("openSocket() failed. reason: Bad hostname \"%s\"\n",
481
/* rfc2732 compliance */
483
if (hname != NULL && hname[0] == '[' && hname[strlen(hname) - 1] == ']') {
484
hname = allocStr(hostname + 1, -1);
485
hname[strlen(hname) - 1] = '\0';
486
if (strspn(hname, "0123456789abcdefABCDEF:.") != strlen(hname))
489
for (af = ai_family_order_table[DNS_order];; af++) {
490
memset(&hints, 0, sizeof(hints));
491
hints.ai_family = *af;
492
hints.ai_socktype = SOCK_STREAM;
493
if (remoteport_num != 0) {
494
Str portbuf = Sprintf("%d", remoteport_num);
495
error = getaddrinfo(hname, portbuf->ptr, &hints, &res0);
500
if (error && remoteport_name && remoteport_name[0] != '\0') {
501
/* try default port */
502
error = getaddrinfo(hname, remoteport_name, &hints, &res0);
505
if (*af == PF_UNSPEC) {
508
/* try next ai family */
512
for (res = res0; res; res = res->ai_next) {
513
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
517
if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
526
if (*af == PF_UNSPEC) {
529
/* try next ai family */
535
#else /* not INET6 */
536
s_port = htons(remoteport_num);
537
bzero((char *)&hostaddr, sizeof(struct sockaddr_in));
538
if ((proto = getprotobyname("tcp")) == NULL) {
539
/* protocol number of TCP is 6 */
540
proto = New(struct protoent);
543
if ((sock = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0) {
545
sock_log("openSocket: socket() failed. reason: %s\n", strerror(errno));
549
regexCompile("^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$", 0);
550
if (regexMatch(hostname, -1, 1)) {
551
sscanf(hostname, "%d.%d.%d.%d", &a1, &a2, &a3, &a4);
552
adr = htonl((a1 << 24) | (a2 << 16) | (a3 << 8) | a4);
553
bcopy((void *)&adr, (void *)&hostaddr.sin_addr, sizeof(long));
554
hostaddr.sin_family = AF_INET;
555
hostaddr.sin_port = s_port;
557
message(Sprintf("Connecting to %s", hostname)->ptr, 0, 0);
560
if (connect(sock, (struct sockaddr *)&hostaddr,
561
sizeof(struct sockaddr_in)) < 0) {
563
sock_log("openSocket: connect() failed. reason: %s\n",
573
message(Sprintf("Performing hostname lookup on %s", hostname)->ptr,
577
if ((entry = gethostbyname(hostname)) == NULL) {
579
sock_log("openSocket: gethostbyname() failed. reason: %s\n",
584
hostaddr.sin_family = AF_INET;
585
hostaddr.sin_port = s_port;
586
for (h_addr_list = entry->h_addr_list; *h_addr_list; h_addr_list++) {
587
bcopy((void *)h_addr_list[0], (void *)&hostaddr.sin_addr,
590
adr = ntohl(*(long *)&hostaddr.sin_addr);
591
sock_log("openSocket: connecting %d.%d.%d.%d\n",
593
(adr >> 16) & 0xff, (adr >> 8) & 0xff, adr & 0xff);
596
message(Sprintf("Connecting to %s", hostname)->ptr, 0, 0);
599
if ((result = connect(sock, (struct sockaddr *)&hostaddr,
600
sizeof(struct sockaddr_in))) == 0) {
605
sock_log("openSocket: connect() failed. reason: %s\n",
614
#endif /* not INET6 */
625
#define COPYPATH_SPC_ALLOW 0
626
#define COPYPATH_SPC_IGNORE 1
627
#define COPYPATH_SPC_REPLACE 2
630
copyPath(char *orgpath, int length, int option)
633
while (*orgpath && length != 0) {
634
if (IS_SPACE(*orgpath)) {
636
case COPYPATH_SPC_ALLOW:
637
Strcat_char(tmp, *orgpath);
639
case COPYPATH_SPC_IGNORE:
642
case COPYPATH_SPC_REPLACE:
643
Strcat_charp(tmp, "%20");
648
Strcat_char(tmp, *orgpath);
656
parseURL(char *url, ParsedURL *p_url, ParsedURL *current)
661
url = url_quote(url); /* quote 0x01-0x20, 0x7F-0xFF */
664
p_url->scheme = SCM_MISSING;
669
p_url->is_nocache = 0;
671
p_url->real_file = NULL;
675
/* RFC1808: Relative Uniform Resource Locators
676
* 4. Resolving Relative URLs
678
if (*url == '\0' || *url == '#') {
680
copyParsedURL(p_url, current);
683
#if defined( __EMX__ ) || defined( __CYGWIN__ )
684
if (!strncmp(url, "file://localhost/", 17)) {
685
p_url->scheme = SCM_LOCAL;
690
#ifdef SUPPORT_DOS_DRIVE_PREFIX
691
if (IS_ALPHA(*p) && (p[1] == ':' || p[1] == '|')) {
692
p_url->scheme = SCM_LOCAL;
695
#endif /* SUPPORT_DOS_DRIVE_PREFIX */
696
/* search for scheme */
697
p_url->scheme = getURLScheme(&p);
698
if (p_url->scheme == SCM_MISSING) {
699
/* scheme part is not found in the url. This means either
700
* (a) the url is relative to the current or (b) the url
701
* denotes a filename (therefore the scheme is SCM_LOCAL).
704
switch (current->scheme) {
707
p_url->scheme = SCM_LOCAL;
711
p_url->scheme = SCM_FTP;
716
p_url->scheme = SCM_NNTP;
720
p_url->scheme = SCM_NEWS;
724
p_url->scheme = current->scheme;
729
p_url->scheme = SCM_LOCAL;
731
if (!strncmp(p, "//", 2)) {
732
/* URL begins with // */
733
/* it means that 'scheme:' is abbreviated */
737
/* the url doesn't begin with '//' */
740
/* scheme part has been found */
741
if (p_url->scheme == SCM_UNKNOWN) {
742
p_url->file = allocStr(url, -1);
745
/* get host and port */
746
if (p[0] != '/' || p[1] != '/') { /* scheme:foo or scheme:/foo */
748
if (p_url->scheme != SCM_UNKNOWN)
749
p_url->port = DefaultPort[p_url->scheme];
754
/* after here, p begins with // */
755
if (p_url->scheme == SCM_LOCAL) { /* file://foo */
760
if (p[2] == '/' || p[2] == '~'
761
/* <A HREF="file:///foo">file:///foo</A> or <A HREF="file://~user">file://~user</A> */
762
#ifdef SUPPORT_DOS_DRIVE_PREFIX
763
|| (IS_ALPHA(p[2]) && (p[3] == ':' || p[3] == '|'))
764
/* <A HREF="file://DRIVE/foo">file://DRIVE/foo</A> */
765
#endif /* SUPPORT_DOS_DRIVE_PREFIX */
772
p += 2; /* scheme://foo */
777
if (*q == '[') { /* rfc2732,rfc2373 compliance */
779
while (IS_XDIGIT(*p) || *p == ':' || *p == '.')
781
if (*p != ']' || (*(p + 1) && strchr(":/?#", *(p + 1)) == NULL))
785
while (*p && strchr(":/@?#", *p) == NULL)
789
/* scheme://user:pass@host or
792
p_url->host = copyPath(q, p - q, COPYPATH_SPC_IGNORE);
794
while (*p && strchr("@/?#", *p) == NULL)
797
/* scheme://user:pass@... */
798
p_url->pass = copyPath(q, p - q, COPYPATH_SPC_ALLOW);
800
p_url->user = p_url->host;
804
/* scheme://host:port/ */
805
tmp = Strnew_charp_n(q, p - q);
806
p_url->port = atoi(tmp->ptr);
807
/* *p is one of ['\0', '/', '?', '#'] */
810
/* scheme://user@... */
811
p_url->user = copyPath(q, p - q, COPYPATH_SPC_IGNORE);
819
p_url->host = copyPath(q, p - q, COPYPATH_SPC_IGNORE);
820
p_url->port = DefaultPort[p_url->scheme];
824
#ifndef SUPPORT_NETBIOS_SHARE
825
if (p_url->scheme == SCM_LOCAL && p_url->user == NULL &&
826
p_url->host != NULL && *p_url->host != '\0' &&
827
strcmp(p_url->host, "localhost")) {
829
* In the environments other than CYGWIN, a URL like
830
* file://host/file is regarded as ftp://host/file.
831
* On the other hand, file://host/file on CYGWIN is
832
* regarded as local access to the file //host/file.
833
* `host' is a netbios-hostname, drive, or any other
834
* name; It is CYGWIN system call who interprets that.
837
p_url->scheme = SCM_FTP; /* ftp://host/... */
838
if (p_url->port == 0)
839
p_url->port = DefaultPort[SCM_FTP];
842
if ((*p == '\0' || *p == '#' || *p == '?') && p_url->host == NULL) {
846
#ifdef SUPPORT_DOS_DRIVE_PREFIX
847
if (p_url->scheme == SCM_LOCAL) {
851
if (IS_ALPHA(q[0]) && (q[1] == ':' || q[1] == '|')) {
864
if (p_url->scheme == SCM_GOPHER) {
867
if (*q && q[0] != '/' && q[1] != '/' && q[2] == '/')
870
#endif /* USE_GOPHER */
873
if (*p == '\0' || *p == '#' || *p == '?') { /* scheme://host[:port]/ */
874
p_url->file = DefaultFile(p_url->scheme);
878
if (p_url->scheme == SCM_GOPHER && *p == 'R') {
881
Strcat_char(tmp, *(p++));
882
while (*p && *p != '/')
884
Strcat_charp(tmp, p);
887
p_url->file = copyPath(tmp->ptr, -1, COPYPATH_SPC_IGNORE);
890
#endif /* USE_GOPHER */
892
char *cgi = strchr(p, '?');
894
while (*p && *p != '#' && p != cgi)
896
if (*p == '#' && p_url->scheme == SCM_LOCAL) {
898
* According to RFC2396, # means the beginning of
899
* URI-reference, and # should be escaped. But,
900
* if the scheme is SCM_LOCAL, the special
901
* treatment will apply to # for convinience.
903
if (p > q && *(p - 1) == '/' && (cgi == NULL || p < cgi)) {
905
* # comes as the first character of the file name
906
* that means, # is not a label but a part of the file
912
else if (*(p + 1) == '\0') {
914
* # comes as the last character of the file name that
915
* means, # is not a label but a part of the file
921
if (p_url->scheme == SCM_LOCAL || p_url->scheme == SCM_MISSING)
922
p_url->file = copyPath(q, p - q, COPYPATH_SPC_ALLOW);
924
p_url->file = copyPath(q, p - q, COPYPATH_SPC_IGNORE);
930
while (*p && *p != '#')
932
p_url->query = copyPath(q, p - q, COPYPATH_SPC_ALLOW);
935
if (p_url->scheme == SCM_MISSING) {
936
p_url->scheme = SCM_LOCAL;
937
p_url->file = allocStr(p, -1);
941
p_url->label = allocStr(p + 1, -1);
946
#define initParsedURL(p) bzero(p,sizeof(ParsedURL))
947
#define ALLOC_STR(s) ((s)==NULL?NULL:allocStr(s,-1))
950
copyParsedURL(ParsedURL *p, ParsedURL *q)
952
p->scheme = q->scheme;
954
p->is_nocache = q->is_nocache;
955
p->user = ALLOC_STR(q->user);
956
p->pass = ALLOC_STR(q->pass);
957
p->host = ALLOC_STR(q->host);
958
p->file = ALLOC_STR(q->file);
959
p->real_file = ALLOC_STR(q->real_file);
960
p->label = ALLOC_STR(q->label);
961
p->query = ALLOC_STR(q->query);
965
parseURL2(char *url, ParsedURL *pu, ParsedURL *current)
969
int relative_uri = FALSE;
971
parseURL(url, pu, current);
972
#ifndef USE_W3MMAILER
973
if (pu->scheme == SCM_MAILTO)
976
if (pu->scheme == SCM_DATA)
978
if (pu->scheme == SCM_NEWS || pu->scheme == SCM_NEWS_GROUP) {
979
if (pu->file && !strchr(pu->file, '@') &&
980
(!(p = strchr(pu->file, '/')) || strchr(p + 1, '-') ||
982
pu->scheme = SCM_NEWS_GROUP;
984
pu->scheme = SCM_NEWS;
987
if (pu->scheme == SCM_NNTP || pu->scheme == SCM_NNTP_GROUP) {
988
if (pu->file && *pu->file == '/')
989
pu->file = allocStr(pu->file + 1, -1);
990
if (pu->file && !strchr(pu->file, '@') &&
991
(!(p = strchr(pu->file, '/')) || strchr(p + 1, '-') ||
993
pu->scheme = SCM_NNTP_GROUP;
995
pu->scheme = SCM_NNTP;
996
if (current && (current->scheme == SCM_NNTP ||
997
current->scheme == SCM_NNTP_GROUP)) {
998
if (pu->host == NULL) {
999
pu->host = current->host;
1000
pu->port = current->port;
1005
if (pu->scheme == SCM_LOCAL) {
1006
char *q = expandName(file_unquote(pu->file));
1007
#ifdef SUPPORT_DOS_DRIVE_PREFIX
1009
if (IS_ALPHA(q[0]) && q[1] == ':') {
1010
drive = Strnew_charp_n(q, 2);
1011
Strcat_charp(drive, file_quote(q+2));
1012
pu->file = drive->ptr;
1016
pu->file = file_quote(q);
1019
if (current && (pu->scheme == current->scheme ||
1020
(pu->scheme == SCM_FTP && current->scheme == SCM_FTPDIR) ||
1021
(pu->scheme == SCM_LOCAL &&
1022
current->scheme == SCM_LOCAL_CGI))
1023
&& pu->host == NULL) {
1024
/* Copy omitted element from the current URL */
1025
pu->user = current->user;
1026
pu->pass = current->pass;
1027
pu->host = current->host;
1028
pu->port = current->port;
1029
if (pu->file && *pu->file) {
1030
#ifdef USE_EXTERNAL_URI_LOADER
1031
if (pu->scheme == SCM_UNKNOWN
1032
&& strchr(pu->file, ':') == NULL
1033
&& current && (p = strchr(current->file, ':')) != NULL) {
1034
pu->file = Sprintf("%s:%s",
1035
allocStr(current->file,
1036
p - current->file), pu->file)->ptr;
1042
pu->scheme != SCM_GOPHER &&
1043
#endif /* USE_GOPHER */
1045
#ifdef SUPPORT_DOS_DRIVE_PREFIX
1046
&& !(pu->scheme == SCM_LOCAL && IS_ALPHA(pu->file[0])
1047
&& pu->file[1] == ':')
1050
/* file is relative [process 1] */
1052
if (current->file) {
1053
tmp = Strnew_charp(current->file);
1054
while (tmp->length > 0) {
1055
if (Strlastchar(tmp) == '/')
1059
Strcat_charp(tmp, p);
1060
pu->file = tmp->ptr;
1061
relative_uri = TRUE;
1065
else if (pu->scheme == SCM_GOPHER && pu->file[0] == '/') {
1067
pu->file = allocStr(p + 1, -1);
1069
#endif /* USE_GOPHER */
1071
else { /* scheme:[?query][#label] */
1072
pu->file = current->file;
1074
pu->query = current->query;
1076
/* comment: query part need not to be completed
1077
* from the current URL. */
1081
if (pu->scheme == SCM_LOCAL) {
1082
if (strncmp(pu->file, "/$LIB/", 6)) {
1083
char abs[_MAX_PATH];
1085
_abspath(abs, file_unquote(pu->file), _MAX_PATH);
1086
pu->file = file_quote(cleanupName(abs));
1090
if (pu->scheme == SCM_LOCAL && pu->file[0] != '/' &&
1091
#ifdef SUPPORT_DOS_DRIVE_PREFIX /* for 'drive:' */
1092
!(IS_ALPHA(pu->file[0]) && pu->file[1] == ':') &&
1094
strcmp(pu->file, "-")) {
1095
/* local file, relative path */
1096
tmp = Strnew_charp(CurrentDir);
1097
if (Strlastchar(tmp) != '/')
1098
Strcat_char(tmp, '/');
1099
Strcat_charp(tmp, file_unquote(pu->file));
1100
pu->file = file_quote(cleanupName(tmp->ptr));
1103
else if (pu->scheme == SCM_HTTP
1105
|| pu->scheme == SCM_HTTPS
1109
/* In this case, pu->file is created by [process 1] above.
1110
* pu->file may contain relative path (for example,
1111
* "/foo/../bar/./baz.html"), cleanupName() must be applied.
1112
* When the entire abs_path is given, it still may contain
1113
* elements like `//', `..' or `.' in the pu->file. It is
1114
* server's responsibility to canonicalize such path.
1116
pu->file = cleanupName(pu->file);
1121
pu->scheme != SCM_GOPHER &&
1122
#endif /* USE_GOPHER */
1123
pu->file[0] == '/') {
1125
* this happens on the following conditions:
1126
* (1) ftp scheme (2) local, looks like absolute path.
1127
* In both case, there must be no side effect with
1128
* cleanupName(). (I hope so...)
1130
pu->file = cleanupName(pu->file);
1132
if (pu->scheme == SCM_LOCAL) {
1133
#ifdef SUPPORT_NETBIOS_SHARE
1134
if (pu->host && strcmp(pu->host, "localhost") != 0) {
1135
Str tmp = Strnew_charp("//");
1136
Strcat_m_charp(tmp, pu->host,
1137
cleanupName(file_unquote(pu->file)), NULL);
1138
pu->real_file = tmp->ptr;
1142
pu->real_file = cleanupName(file_unquote(pu->file));
1148
_parsedURL2Str(ParsedURL *pu, int pass)
1151
static char *scheme_str[] = {
1152
"http", "gopher", "ftp", "ftp", "file", "file", "exec", "nntp", "nntp",
1153
"news", "news", "data", "mailto",
1156
#endif /* USE_SSL */
1159
if (pu->scheme == SCM_MISSING) {
1160
return Strnew_charp("???");
1162
else if (pu->scheme == SCM_UNKNOWN) {
1163
return Strnew_charp(pu->file);
1165
if (pu->host == NULL && pu->file == NULL && pu->label != NULL) {
1167
return Sprintf("#%s", pu->label);
1169
if (pu->scheme == SCM_LOCAL && !strcmp(pu->file, "-")) {
1170
tmp = Strnew_charp("-");
1172
Strcat_char(tmp, '#');
1173
Strcat_charp(tmp, pu->label);
1177
tmp = Strnew_charp(scheme_str[pu->scheme]);
1178
Strcat_char(tmp, ':');
1179
#ifndef USE_W3MMAILER
1180
if (pu->scheme == SCM_MAILTO) {
1181
Strcat_charp(tmp, pu->file);
1183
Strcat_char(tmp, '?');
1184
Strcat_charp(tmp, pu->query);
1189
if (pu->scheme == SCM_DATA) {
1190
Strcat_charp(tmp, pu->file);
1194
if (pu->scheme != SCM_NEWS && pu->scheme != SCM_NEWS_GROUP)
1195
#endif /* USE_NNTP */
1197
Strcat_charp(tmp, "//");
1200
Strcat_charp(tmp, pu->user);
1201
if (pass && pu->pass) {
1202
Strcat_char(tmp, ':');
1203
Strcat_charp(tmp, pu->pass);
1205
Strcat_char(tmp, '@');
1208
Strcat_charp(tmp, pu->host);
1209
if (pu->port != DefaultPort[pu->scheme]) {
1210
Strcat_char(tmp, ':');
1211
Strcat(tmp, Sprintf("%d", pu->port));
1216
pu->scheme != SCM_NEWS && pu->scheme != SCM_NEWS_GROUP &&
1217
#endif /* USE_NNTP */
1218
(pu->file == NULL || (pu->file[0] != '/'
1219
#ifdef SUPPORT_DOS_DRIVE_PREFIX
1220
&& !(IS_ALPHA(pu->file[0])
1221
&& pu->file[1] == ':'
1222
&& pu->host == NULL)
1225
Strcat_char(tmp, '/');
1226
Strcat_charp(tmp, pu->file);
1227
if (pu->scheme == SCM_FTPDIR && Strlastchar(tmp) != '/')
1228
Strcat_char(tmp, '/');
1230
Strcat_char(tmp, '?');
1231
Strcat_charp(tmp, pu->query);
1234
Strcat_char(tmp, '#');
1235
Strcat_charp(tmp, pu->label);
1241
parsedURL2Str(ParsedURL *pu)
1243
return _parsedURL2Str(pu, FALSE);
1247
getURLScheme(char **url)
1251
int scheme = SCM_MISSING;
1253
while (*p && (IS_ALNUM(*p) || *p == '.' || *p == '+' || *p == '-'))
1255
if (*p == ':') { /* scheme found */
1256
scheme = SCM_UNKNOWN;
1257
for (i = 0; (q = schemetable[i].cmdname) != NULL; i++) {
1258
int len = strlen(q);
1259
if (!strncasecmp(q, *url, len) && (*url)[len] == ':') {
1260
scheme = schemetable[i].cmd;
1270
otherinfo(ParsedURL *target, ParsedURL *current, char *referer)
1274
Strcat_charp(s, "User-Agent: ");
1275
if (UserAgent == NULL || *UserAgent == '\0')
1276
Strcat_charp(s, w3m_version);
1278
Strcat_charp(s, UserAgent);
1279
Strcat_charp(s, "\r\n");
1281
Strcat_m_charp(s, "Accept: ", AcceptMedia, "\r\n", NULL);
1282
Strcat_m_charp(s, "Accept-Encoding: ", AcceptEncoding, "\r\n", NULL);
1283
Strcat_m_charp(s, "Accept-Language: ", AcceptLang, "\r\n", NULL);
1286
Strcat_charp(s, "Host: ");
1287
Strcat_charp(s, target->host);
1288
if (target->port != DefaultPort[target->scheme])
1289
Strcat(s, Sprintf(":%d", target->port));
1290
Strcat_charp(s, "\r\n");
1292
if (target->is_nocache || NoCache) {
1293
Strcat_charp(s, "Pragma: no-cache\r\n");
1294
Strcat_charp(s, "Cache-control: no-cache\r\n");
1296
if (!NoSendReferer) {
1297
if (referer == NULL && current && current->scheme != SCM_LOCAL &&
1298
(current->scheme != SCM_FTP ||
1299
(current->user == NULL && current->pass == NULL))) {
1300
char *p = current->label;
1301
Strcat_charp(s, "Referer: ");
1302
current->label = NULL;
1303
Strcat(s, parsedURL2Str(current));
1305
Strcat_charp(s, "\r\n");
1307
else if (referer != NULL && referer != NO_REFERER) {
1308
char *p = strchr(referer, '#');
1309
Strcat_charp(s, "Referer: ");
1311
Strcat_charp_n(s, referer, p - referer);
1313
Strcat_charp(s, referer);
1314
Strcat_charp(s, "\r\n");
1321
HTTPrequestMethod(HRequest *hr)
1323
switch (hr->command) {
1324
case HR_COMMAND_CONNECT:
1325
return Strnew_charp("CONNECT");
1326
case HR_COMMAND_POST:
1327
return Strnew_charp("POST");
1329
case HR_COMMAND_HEAD:
1330
return Strnew_charp("HEAD");
1332
case HR_COMMAND_GET:
1334
return Strnew_charp("GET");
1340
HTTPrequestURI(ParsedURL *pu, HRequest *hr)
1343
if (hr->command == HR_COMMAND_CONNECT) {
1344
Strcat_charp(tmp, pu->host);
1345
Strcat(tmp, Sprintf(":%d", pu->port));
1347
else if (hr->flag & HR_FLAG_LOCAL) {
1348
Strcat_charp(tmp, pu->file);
1350
Strcat_char(tmp, '?');
1351
Strcat_charp(tmp, pu->query);
1355
char *save_label = pu->label;
1357
Strcat(tmp, _parsedURL2Str(pu, TRUE));
1358
pu->label = save_label;
1364
HTTPrequest(ParsedURL *pu, ParsedURL *current, HRequest *hr, TextList *extra)
1368
int seen_www_auth = 0;
1369
int seen_proxy_auth = 0;
1372
#endif /* USE_COOKIE */
1373
tmp = HTTPrequestMethod(hr);
1374
Strcat_charp(tmp, " ");
1375
Strcat_charp(tmp, HTTPrequestURI(pu, hr)->ptr);
1376
Strcat_charp(tmp, " HTTP/1.0\r\n");
1377
if (hr->referer == NO_REFERER)
1378
Strcat_charp(tmp, otherinfo(pu, NULL, NULL));
1380
Strcat_charp(tmp, otherinfo(pu, current, hr->referer));
1382
for (i = extra->first; i != NULL; i = i->next) {
1383
if (strncasecmp(i->ptr, "Authorization:",
1384
sizeof("Authorization:") - 1) == 0) {
1387
if (hr->command == HR_COMMAND_CONNECT)
1391
if (strncasecmp(i->ptr, "Proxy-Authorization:",
1392
sizeof("Proxy-Authorization:") - 1) == 0) {
1393
seen_proxy_auth = 1;
1395
if (pu->scheme == SCM_HTTPS
1396
&& hr->command != HR_COMMAND_CONNECT)
1400
Strcat_charp(tmp, i->ptr);
1404
if (hr->command != HR_COMMAND_CONNECT &&
1405
use_cookie && (cookie = find_cookie(pu))) {
1406
Strcat_charp(tmp, "Cookie: ");
1407
Strcat(tmp, cookie);
1408
Strcat_charp(tmp, "\r\n");
1409
/* [DRAFT 12] s. 10.1 */
1410
if (cookie->ptr[0] != '$')
1411
Strcat_charp(tmp, "Cookie2: $Version=\"1\"\r\n");
1413
#endif /* USE_COOKIE */
1414
if (hr->command == HR_COMMAND_POST) {
1415
if (hr->request->enctype == FORM_ENCTYPE_MULTIPART) {
1416
Strcat_charp(tmp, "Content-type: multipart/form-data; boundary=");
1417
Strcat_charp(tmp, hr->request->boundary);
1418
Strcat_charp(tmp, "\r\n");
1420
Sprintf("Content-length: %ld\r\n", hr->request->length));
1421
Strcat_charp(tmp, "\r\n");
1424
if (!override_content_type) {
1426
"Content-type: application/x-www-form-urlencoded\r\n");
1429
Sprintf("Content-length: %ld\r\n", hr->request->length));
1431
Strcat(tmp, header_string);
1432
Strcat_charp(tmp, "\r\n");
1433
Strcat_charp_n(tmp, hr->request->body, hr->request->length);
1434
Strcat_charp(tmp, "\r\n");
1439
Strcat(tmp, header_string);
1440
Strcat_charp(tmp, "\r\n");
1443
fprintf(stderr, "HTTPrequest: [ %s ]\n\n", tmp->ptr);
1449
init_stream(URLFile *uf, int scheme, InputStream stream)
1451
memset(uf, 0, sizeof(URLFile));
1452
uf->stream = stream;
1453
uf->scheme = scheme;
1454
uf->encoding = ENC_7BIT;
1456
uf->compression = 0;
1457
uf->guess_type = NULL;
1463
openURL(char *url, ParsedURL *pu, ParsedURL *current,
1464
URLOption *option, FormList *request, TextList *extra_header,
1465
URLFile *ouf, HRequest *hr, unsigned char *status)
1474
#endif /* USE_SSL */
1483
init_stream(&uf, SCM_MISSING, NULL);
1487
scheme = getURLScheme(&u);
1488
if (current == NULL && scheme == SCM_MISSING && !ArgvIsURL)
1489
u = file_to_url(url); /* force to local file */
1493
parseURL2(u, pu, current);
1494
if (pu->scheme == SCM_LOCAL && pu->file == NULL) {
1495
if (pu->label != NULL) {
1496
/* #hogege is not a label but a filename */
1497
Str tmp2 = Strnew_charp("#");
1498
Strcat_charp(tmp2, pu->label);
1499
pu->file = tmp2->ptr;
1500
pu->real_file = cleanupName(file_unquote(pu->file));
1504
/* given URL must be null string */
1506
sock_log("given URL must be null string\n");
1512
uf.scheme = pu->scheme;
1513
uf.url = parsedURL2Str(pu)->ptr;
1514
pu->is_nocache = (option->flag & RG_NOCACHE);
1515
uf.ext = filename_extension(pu->file, 1);
1517
hr->command = HR_COMMAND_GET;
1519
hr->referer = option->referer;
1520
hr->request = request;
1522
switch (pu->scheme) {
1525
if (request && request->body)
1526
/* local CGI: POST */
1527
uf.stream = newFileStream(localcgi_post(pu->real_file, pu->query,
1528
request, option->referer),
1529
(void (*)())pclose);
1531
/* lodal CGI: GET */
1532
uf.stream = newFileStream(localcgi_get(pu->real_file, pu->query,
1534
(void (*)())pclose);
1537
uf.scheme = pu->scheme = SCM_LOCAL_CGI;
1540
examineFile(pu->real_file, &uf);
1541
if (uf.stream == NULL) {
1542
if (dir_exist(pu->real_file)) {
1543
add_index_file(pu, &uf);
1544
if (uf.stream == NULL)
1547
else if (document_root != NULL) {
1548
tmp = Strnew_charp(document_root);
1549
if (Strlastchar(tmp) != '/' && pu->file[0] != '/')
1550
Strcat_char(tmp, '/');
1551
Strcat_charp(tmp, pu->file);
1552
p = cleanupName(tmp->ptr);
1553
q = cleanupName(file_unquote(p));
1557
add_index_file(pu, &uf);
1558
if (uf.stream == NULL) {
1563
examineFile(q, &uf);
1571
if (uf.stream == NULL && retryAsHttp && url[0] != '/') {
1572
if (scheme == SCM_MISSING || scheme == SCM_UNKNOWN) {
1573
/* retry it as "http://" */
1574
u = Strnew_m_charp("http://", url, NULL)->ptr;
1581
if (pu->file == NULL)
1582
pu->file = allocStr("/", -1);
1583
if (non_null(FTP_proxy) &&
1584
!Do_not_use_proxy &&
1585
pu->host != NULL && !check_no_proxy(pu->host)) {
1586
hr->flag |= HR_FLAG_PROXY;
1587
sock = openSocket(FTP_proxy_parsed.host,
1588
schemetable[FTP_proxy_parsed.scheme].cmdname,
1589
FTP_proxy_parsed.port);
1592
uf.scheme = SCM_HTTP;
1593
tmp = HTTPrequest(pu, current, hr, extra_header);
1594
write(sock, tmp->ptr, tmp->length);
1597
uf.stream = openFTPStream(pu, &uf);
1598
uf.scheme = pu->scheme;
1605
#endif /* USE_SSL */
1606
if (pu->file == NULL)
1607
pu->file = allocStr("/", -1);
1608
if (request && request->method == FORM_METHOD_POST && request->body)
1609
hr->command = HR_COMMAND_POST;
1610
if (request && request->method == FORM_METHOD_HEAD)
1611
hr->command = HR_COMMAND_HEAD;
1614
(pu->scheme == SCM_HTTPS) ? non_null(HTTPS_proxy) :
1615
#endif /* USE_SSL */
1616
non_null(HTTP_proxy)) && !Do_not_use_proxy &&
1617
pu->host != NULL && !check_no_proxy(pu->host)) {
1618
hr->flag |= HR_FLAG_PROXY;
1620
if (pu->scheme == SCM_HTTPS && *status == HTST_CONNECT) {
1621
sock = ssl_socket_of(ouf->stream);
1622
if (!(sslh = openSSLHandle(sock, pu->host,
1623
&uf.ssl_certificate))) {
1624
*status = HTST_MISSING;
1628
else if (pu->scheme == SCM_HTTPS) {
1629
sock = openSocket(HTTPS_proxy_parsed.host,
1630
schemetable[HTTPS_proxy_parsed.scheme].
1631
cmdname, HTTPS_proxy_parsed.port);
1635
#endif /* USE_SSL */
1636
sock = openSocket(HTTP_proxy_parsed.host,
1637
schemetable[HTTP_proxy_parsed.scheme].
1638
cmdname, HTTP_proxy_parsed.port);
1642
#endif /* USE_SSL */
1645
sock_log("Can't open socket\n");
1650
if (pu->scheme == SCM_HTTPS) {
1651
if (*status == HTST_NORMAL) {
1652
hr->command = HR_COMMAND_CONNECT;
1653
tmp = HTTPrequest(pu, current, hr, extra_header);
1654
*status = HTST_CONNECT;
1657
hr->flag |= HR_FLAG_LOCAL;
1658
tmp = HTTPrequest(pu, current, hr, extra_header);
1659
*status = HTST_NORMAL;
1663
#endif /* USE_SSL */
1665
tmp = HTTPrequest(pu, current, hr, extra_header);
1666
*status = HTST_NORMAL;
1670
sock = openSocket(pu->host,
1671
schemetable[pu->scheme].cmdname, pu->port);
1673
*status = HTST_MISSING;
1677
if (pu->scheme == SCM_HTTPS) {
1678
if (!(sslh = openSSLHandle(sock, pu->host,
1679
&uf.ssl_certificate))) {
1680
*status = HTST_MISSING;
1684
#endif /* USE_SSL */
1685
hr->flag |= HR_FLAG_LOCAL;
1686
tmp = HTTPrequest(pu, current, hr, extra_header);
1687
*status = HTST_NORMAL;
1690
if (pu->scheme == SCM_HTTPS) {
1691
uf.stream = newSSLStream(sslh, sock);
1693
SSL_write(sslh, tmp->ptr, tmp->length);
1695
write(sock, tmp->ptr, tmp->length);
1698
FILE *ff = fopen("zzrequest", "a");
1700
fputs("HTTPS: request via SSL\n", ff);
1702
fputs("HTTPS: request without SSL\n", ff);
1703
fwrite(tmp->ptr, sizeof(char), tmp->length, ff);
1706
#endif /* HTTP_DEBUG */
1707
if (hr->command == HR_COMMAND_POST &&
1708
request->enctype == FORM_ENCTYPE_MULTIPART) {
1710
SSL_write_from_file(sslh, request->body);
1712
write_from_file(sock, request->body);
1717
#endif /* USE_SSL */
1719
write(sock, tmp->ptr, tmp->length);
1722
FILE *ff = fopen("zzrequest", "a");
1723
fwrite(tmp->ptr, sizeof(char), tmp->length, ff);
1726
#endif /* HTTP_DEBUG */
1727
if (hr->command == HR_COMMAND_POST &&
1728
request->enctype == FORM_ENCTYPE_MULTIPART)
1729
write_from_file(sock, request->body);
1734
if (non_null(GOPHER_proxy) &&
1735
!Do_not_use_proxy &&
1736
pu->host != NULL && !check_no_proxy(pu->host)) {
1737
hr->flag |= HR_FLAG_PROXY;
1738
sock = openSocket(GOPHER_proxy_parsed.host,
1739
schemetable[GOPHER_proxy_parsed.scheme].cmdname,
1740
GOPHER_proxy_parsed.port);
1743
uf.scheme = SCM_HTTP;
1744
tmp = HTTPrequest(pu, current, hr, extra_header);
1747
sock = openSocket(pu->host,
1748
schemetable[pu->scheme].cmdname, pu->port);
1751
if (pu->file == NULL)
1753
tmp = Strnew_charp(file_unquote(pu->file));
1754
Strcat_char(tmp, '\n');
1756
write(sock, tmp->ptr, tmp->length);
1758
#endif /* USE_GOPHER */
1761
case SCM_NNTP_GROUP:
1763
case SCM_NEWS_GROUP:
1764
if (pu->scheme == SCM_NNTP || pu->scheme == SCM_NEWS)
1765
uf.scheme = SCM_NEWS;
1767
uf.scheme = SCM_NEWS_GROUP;
1768
uf.stream = openNewsStream(pu);
1770
#endif /* USE_NNTP */
1772
if (pu->file == NULL)
1774
p = Strnew_charp(pu->file)->ptr;
1779
tmp = Strnew_charp(q);
1780
q = strrchr(p, ';');
1781
if (q != NULL && !strcmp(q, ";base64")) {
1783
uf.encoding = ENC_BASE64;
1786
tmp = Str_url_unquote(tmp, FALSE, FALSE);
1787
uf.stream = newStrStream(tmp);
1788
uf.guess_type = (*p != '\0') ? p : "text/plain";
1794
uf.stream = newInputStream(sock);
1798
/* add index_file if exists */
1800
add_index_file(ParsedURL *pu, URLFile *uf)
1804
if (index_file == NULL || index_file[0] == '\0') {
1808
p = Strnew_m_charp(pu->file, "/", file_quote(index_file), NULL)->ptr;
1810
q = cleanupName(file_unquote(p));
1812
if (uf->stream == NULL)
1820
guessContentTypeFromTable(struct table2 *table, char *filename)
1826
p = &filename[strlen(filename) - 1];
1827
while (filename < p && *p != '.')
1832
for (t = table; t->item1; t++) {
1833
if (!strcmp(p, t->item1))
1836
for (t = table; t->item1; t++) {
1837
if (!strcasecmp(p, t->item1))
1844
guessContentType(char *filename)
1849
if (filename == NULL)
1851
if (mimetypes_list == NULL)
1852
goto no_user_mimetypes;
1854
for (i = 0; i < mimetypes_list->nitem; i++) {
1856
guessContentTypeFromTable(UserMimeTypes[i], filename)) != NULL)
1861
return guessContentTypeFromTable(DefaultGuess, filename);
1865
make_domain_list(char *domain_list)
1869
TextList *domains = NULL;
1872
tmp = Strnew_size(64);
1874
while (*p && IS_SPACE(*p))
1877
while (*p && !IS_SPACE(*p) && *p != ',')
1878
Strcat_char(tmp, *p++);
1879
if (tmp->length > 0) {
1880
if (domains == NULL)
1881
domains = newTextList();
1882
pushText(domains, tmp->ptr);
1884
while (*p && IS_SPACE(*p))
1893
domain_match(char *pat, char *domain)
1900
if (!strcasecmp(pat, domain))
1902
domain = strchr(domain, '.');
1910
check_no_proxy(char *domain)
1913
volatile int ret = 0;
1914
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
1916
if (NO_proxy_domains == NULL || NO_proxy_domains->nitem == 0 ||
1919
for (tl = NO_proxy_domains->first; tl != NULL; tl = tl->next) {
1920
if (domain_match(tl->ptr, domain))
1923
if (!NOproxy_netaddr) {
1927
* to check noproxy by network addr
1929
if (SETJMP(AbortLoading) != 0) {
1938
unsigned char **h_addr_list;
1939
char addr[4 * 16], buf[5];
1941
he = gethostbyname(domain);
1946
for (h_addr_list = (unsigned char **)he->h_addr_list; *h_addr_list;
1948
sprintf(addr, "%d", h_addr_list[0][0]);
1949
for (n = 1; n < he->h_length; n++) {
1950
sprintf(buf, ".%d", h_addr_list[0][n]);
1953
for (tl = NO_proxy_domains->first; tl != NULL; tl = tl->next) {
1954
if (strncmp(tl->ptr, addr, strlen(tl->ptr)) == 0) {
1962
struct addrinfo hints;
1963
struct addrinfo *res, *res0;
1967
for (af = ai_family_order_table[DNS_order];; af++) {
1968
memset(&hints, 0, sizeof(hints));
1969
hints.ai_family = *af;
1970
error = getaddrinfo(domain, NULL, &hints, &res0);
1972
if (*af == PF_UNSPEC) {
1978
for (res = res0; res != NULL; res = res->ai_next) {
1979
switch (res->ai_family) {
1982
&((struct sockaddr_in *)res->ai_addr)->sin_addr,
1983
addr, sizeof(addr));
1987
&((struct sockaddr_in6 *)res->ai_addr)->
1988
sin6_addr, addr, sizeof(addr));
1994
for (tl = NO_proxy_domains->first; tl != NULL; tl = tl->next) {
1995
if (strncmp(tl->ptr, addr, strlen(tl->ptr)) == 0) {
2003
if (*af == PF_UNSPEC) {
2015
filename_extension(char *path, int is_url)
2017
char *last_dot = "", *p = path;
2028
else if (is_url && *p == '?')
2031
if (*last_dot == '.') {
2032
for (i = 1; last_dot[i] && i < 8; i++) {
2033
if (is_url && !IS_ALNUM(last_dot[i]))
2036
return allocStr(last_dot, i);
2042
#ifdef USE_EXTERNAL_URI_LOADER
2043
static struct table2 **urimethods;
2044
static struct table2 default_urimethods[] = {
2045
{"mailto", "file:///$LIB/w3mmail.cgi?%s"},
2049
static struct table2 *
2050
loadURIMethods(char *filename)
2058
f = fopen(expandPath(filename), "r");
2062
while (tmp = Strfgets(f), tmp->length > 0) {
2063
if (tmp->ptr[0] != '#')
2068
um = New_N(struct table2, n + 1);
2070
while (tmp = Strfgets(f), tmp->length > 0) {
2071
if (tmp->ptr[0] == '#')
2073
while (IS_SPACE(Strlastchar(tmp)))
2075
for (up = p = tmp->ptr; *p != '\0'; p++) {
2077
um[i].item1 = Strnew_charp_n(up, p - up)->ptr;
2084
while (*p != '\0' && IS_SPACE(*p))
2086
um[i].item2 = Strnew_charp(p)->ptr;
2098
TextList *methodmap_list = NULL;
2102
if (non_null(urimethodmap_files))
2103
methodmap_list = make_domain_list(urimethodmap_files);
2104
if (methodmap_list == NULL)
2106
urimethods = New_N(struct table2 *, (methodmap_list->nitem + 1));
2107
for (i = 0, tl = methodmap_list->first; tl; tl = tl->next) {
2108
urimethods[i] = loadURIMethods(tl->ptr);
2112
urimethods[i] = NULL;
2116
searchURIMethods(ParsedURL *pu)
2124
if (pu->scheme != SCM_UNKNOWN)
2125
return NULL; /* use internal */
2126
if (urimethods == NULL)
2128
url = parsedURL2Str(pu);
2129
for (p = url->ptr; *p != '\0'; p++) {
2131
scheme = Strnew_charp_n(url->ptr, p - url->ptr);
2139
* RFC2396 3.1. Scheme Component
2140
* For resiliency, programs interpreting URI should treat upper case
2141
* letters as equivalent to lower case in scheme names (e.g., allow
2142
* "HTTP" as well as "http").
2144
for (i = 0; (ump = urimethods[i]) != NULL; i++) {
2145
for (; ump->item1 != NULL; ump++) {
2146
if (strcasecmp(ump->item1, scheme->ptr) == 0) {
2147
return Sprintf(ump->item2, url_quote(url->ptr));
2151
for (ump = default_urimethods; ump->item1 != NULL; ump++) {
2152
if (strcasecmp(ump->item1, scheme->ptr) == 0) {
2153
return Sprintf(ump->item2, url_quote(url->ptr));
2160
* RFC2396: Uniform Resource Identifiers (URI): Generic Syntax
2161
* Appendix A. Collected BNF for URI
2162
* uric = reserved | unreserved | escaped
2163
* reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
2165
* unreserved = alphanum | mark
2166
* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
2168
* escaped = "%" hex hex
2171
#define URI_PATTERN "([-;/?:@&=+$,a-zA-Z0-9_.!~*'()]|%[0-9A-Fa-f][0-9A-Fa-f])*"
2173
chkExternalURIBuffer(Buffer *buf)
2178
for (i = 0; (ump = urimethods[i]) != NULL; i++) {
2179
for (; ump->item1 != NULL; ump++) {
2180
reAnchor(buf, Sprintf("%s:%s", ump->item1, URI_PATTERN)->ptr);
2183
for (ump = default_urimethods; ump->item1 != NULL; ump++) {
2184
reAnchor(buf, Sprintf("%s:%s", ump->item1, URI_PATTERN)->ptr);
2190
schemeToProxy(int scheme)
2192
ParsedURL *pu = NULL; /* for gcc */
2195
pu = &HTTP_proxy_parsed;
2199
pu = &HTTPS_proxy_parsed;
2203
pu = &FTP_proxy_parsed;
2207
pu = &GOPHER_proxy_parsed;