URL url_http_open(char *name) { URL_http *url; SOCKET fd; char *host, *path = NULL, *p; unsigned short port; char buff[BUFSIZ]; char wwwserver[256]; int n; #ifdef DEBUG printf("url_http_open(%s)\n", name); #endif /* DEBUG */ url = (URL_http *)alloc_url(sizeof(URL_http)); if(url == NULL) { url_errno = errno; return NULL; } /* common members */ URLm(url, type) = URL_http_t; URLm(url, url_read) = url_http_read; URLm(url, url_gets) = url_http_gets; URLm(url, url_fgetc) = url_http_fgetc; URLm(url, url_seek) = NULL; URLm(url, url_tell) = NULL; URLm(url, url_close) = url_http_close; /* private members */ url->fp = NULL; if(url_http_proxy_host) { char *q; int len; host = url_http_proxy_host; port = url_http_proxy_port; p = name; if(strncmp(p, "http://", 7) == 0) p += 7; for(q = p; *q && *q != ':' && *q != '/'; q++) ; len = q - p; if(len >= sizeof(wwwserver) - 1) { /* What?? */ strcpy(wwwserver, "localhost"); } else { strncpy(wwwserver, p, len); } } else { if(strncmp(name, "http://", 7) == 0) name += 7; n = strlen(name); if(n + REQUEST_OFFSET >= BUFSIZ) { url_http_close((URL)url); url_errno = URLERR_URLTOOLONG; errno = ENOENT; return NULL; } memcpy(buff, name, n + 1); host = buff; for(p = host; *p && *p != ':' && *p != '/'; p++) ; if(*p == ':') { char *pp; *p++ = '\0'; /* terminate `host' string */ port = atoi(p); pp = strchr(p, '/'); if(pp == NULL) p[0] = '\0'; else p = pp; } else port = 80; path = p; if(*path == '\0') *(path + 1) = '\0'; *path = '\0'; /* terminate `host' string */ strncpy(wwwserver, host, sizeof(wwwserver)); } #ifdef DEBUG printf("open(host=`%s', port=`%d')\n", host, port); #endif /* DEBUG */ #ifdef __W32__ timeout_flag = 0; fd = open_socket(host, port); #else timeout_flag = 0; signal(SIGALRM, timeout); alarm(ALARM_TIMEOUT); fd = open_socket(host, port); alarm(0); signal(SIGALRM, SIG_DFL); #endif /* __W32__ */ if(fd == (SOCKET)-1) { VOLATILE_TOUCH(timeout_flag); #ifdef ETIMEDOUT if(timeout_flag) errno = ETIMEDOUT; #endif /* ETIMEDOUT */ if(errno) url_errno = errno; else { url_errno = URLERR_CANTOPEN; errno = ENOENT; } url_http_close((URL)url); return NULL; } if((url->fp = socket_fdopen(fd, "rb")) == NULL) { url_errno = errno; closesocket(fd); url_http_close((URL)url); errno = url_errno; return NULL; } if(url_http_proxy_host) sprintf(buff, "GET %s HTTP/1.0\r\n", name); else { *path = '/'; sprintf(buff, "GET %s HTTP/1.0\r\n", path); } socket_write(fd, buff, (long)strlen(buff)); #ifdef DEBUG printf("HTTP<%s", buff); #endif /* DEBUG */ if(url_user_agent) { sprintf(buff, "User-Agent: %s\r\n", url_user_agent); socket_write(fd, buff, (long)strlen(buff)); #ifdef DEBUG printf("HTTP<%s", buff); #endif /* DEBUG */ } /* Host field */ sprintf(buff, "Host: %s\r\n", wwwserver); socket_write(fd, buff, (long)strlen(buff)); #ifdef DEBUG printf("HTTP<%s", buff); #endif /* DEBUG */ /* End of header */ socket_write(fd, "\r\n", 2); socket_shutdown(fd, 1); if(socket_fgets(buff, BUFSIZ, url->fp) == NULL) { if(errno) url_errno = errno; else { url_errno = URLERR_CANTOPEN; errno = ENOENT; } url_http_close((URL)url); return NULL; } #ifdef DEBUG printf("HTTP>%s", buff); #endif /* DEBUG */ p = buff; if(strncmp(p, "HTTP/1.0 ", 9) == 0 || strncmp(p, "HTTP/1.1 ", 9) == 0) p += 9; if(strncmp(p, "200", 3) != 0) /* Not success */ { url_http_close((URL)url); url_errno = errno = ENOENT; return NULL; } /* Skip mime header */ while(socket_fgets(buff, BUFSIZ, url->fp) != NULL) { if(buff[0] == '\n' || (buff[0] == '\r' && buff[1] == '\n')) break; /* end of heaer */ #ifdef DEBUG printf("HTTP>%s", buff); #endif /* DEBUG */ } #ifdef __W32__ return url_buff_open((URL)url, 1); #else return (URL)url; #endif /* __W32__ */ }
URL url_news_open(char *name) { URL_news *url; char *host, *p; unsigned short port; char buff[BUFSIZ], messageID[256]; int check_timeout; int i; #ifdef DEBUG fprintf(stderr, "url_news_open(%s)\n", name); #endif /* DEBUG */ url = (URL_news *)alloc_url(sizeof(URL_news)); if(url == NULL) { url_errno = errno; return NULL; } /* common members */ URLm(url, type) = URL_news_t; URLm(url, url_read) = url_news_read; URLm(url, url_gets) = NULL; URLm(url, url_fgetc) = url_news_fgetc; URLm(url, url_seek) = NULL; URLm(url, url_tell) = NULL; URLm(url, url_close) = url_news_close; /* private members */ url->news = NULL; url->status = ARTICLE_STATUS_2; url->eof = 0; if(strncmp(name, "news://", 7) == 0) name += 7; strncpy(buff, name, sizeof(buff) - 1); buff[sizeof(buff) - 1] = '\0'; host = buff; if (host[0] == '[') { if (!(p = strchr(host, ']'))) return NULL; *p = '\0'; ++host; ++p; } else for(p = host; *p && *p != ':' && *p != '/'; p++) ; if(*p == ':') { *p++ = '\0'; /* terminate `host' string */ port = atoi(p); p = strchr(p, '/'); if(p == NULL) { url_errno = URLERR_CANTOPEN; errno = ENOENT; url_news_close((URL)url); return NULL; } } else port = 119; *p++ = '\0'; /* terminate `host' string */ if(*p == '<') p++; strncpy(messageID, p, sizeof(messageID) - 1); messageID[sizeof(messageID) - 1] = '\0'; i = strlen(messageID); if(i > 0 && messageID[i - 1] == '>') messageID[i - 1] = '\0'; #ifdef DEBUG fprintf(stderr, "messageID: <%s>\n", messageID); #endif /* DEBUG */ #ifdef DEBUG fprintf(stderr, "open(host=`%s', port=`%d')\n", host, port); #endif /* DEBUG */ if((url->news = open_news_server(host, port)) == NULL) { url_news_close((URL)url); return NULL; } check_timeout = 1; retry_article: sprintf(buff, "ARTICLE <%s>\r\n", messageID); #ifdef DEBUG fprintf(stderr, "CMD> %s", buff); #endif /* DEBUG */ socket_write(url->news->fd, buff, (long)strlen(buff)); buff[0] = '\0'; if(socket_fgets(buff, sizeof(buff), url->news->fp) == NULL) { if(check_timeout) { check_timeout = 0; close_news_server(url->news); if((url->news = open_news_server(host, port)) != NULL) goto retry_article; } url_news_close((URL)url); url_errno = URLERR_CANTOPEN; errno = ENOENT; return NULL; } #ifdef DEBUG fprintf(stderr, "CMD< %s", buff); #endif /* DEBUG */ if(buff[0] != NNTP_OK_ID) { if(check_timeout && strncmp(buff, "503", 3) == 0) { check_timeout = 0; close_news_server(url->news); if((url->news = open_news_server(host, port)) != NULL) goto retry_article; } url_news_close((URL)url); url_errno = errno = ENOENT; return NULL; } return (URL)url; }
static char *url_http_gets(URL url, char *buff, int n) { URL_http *urlp = (URL_http *)url; return socket_fgets(buff, n, urlp->fp); }
static NewsConnection *open_news_server(char *host, unsigned short port) { NewsConnection *p; char buff[512]; for(p = connection_cache; p != NULL; p = p->next) { if(p->status == 0 && strcmp(p->host, host) == 0 && p->port == port) { p->status = 1; return p; } } for(p = connection_cache; p != NULL; p = p->next) if(p->status == -1) break; if(p == NULL) { if((p = (NewsConnection *)safe_malloc(sizeof(NewsConnection))) == NULL) return NULL; p->next = connection_cache; connection_cache = p; p->status = -1; } if((p->host = safe_strdup(host)) == NULL) return NULL; p->port = port; #ifdef __W32__ timeout_flag = 0; p->fd = open_socket(host, port); #else timeout_flag = 0; signal(SIGALRM, timeout); alarm(ALARM_TIMEOUT); p->fd = open_socket(host, port); alarm(0); signal(SIGALRM, SIG_DFL); #endif /* __W32__ */ if(p->fd == (SOCKET)-1) { int save_errno; VOLATILE_TOUCH(timeout_flag); #ifdef ETIMEDOUT if(timeout_flag) errno = ETIMEDOUT; #endif /* ETIMEDOUT */ if(errno) url_errno = errno; else { url_errno = URLERR_CANTOPEN; errno = ENOENT; } #ifdef DEBUG perror(host); #endif /* DEBUG */ save_errno = errno; free(p->host); errno = save_errno; return NULL; } if((p->fp = socket_fdopen(p->fd, "rb")) == NULL) { url_errno = errno; closesocket(p->fd); free(p->host); errno = url_errno; return NULL; } buff[0] = '\0'; if(socket_fgets(buff, sizeof(buff), p->fp) == NULL) { url_errno = errno; closesocket(p->fd); socket_fclose(p->fp); free(p->host); errno = url_errno; return NULL; } #ifdef DEBUG fprintf(stderr, "Connect status: %s", buff); #endif /* DEBUG */ if(buff[0] != NNTP_OK_ID) { closesocket(p->fd); socket_fclose(p->fp); free(p->host); url_errno = URLERR_CANTOPEN; errno = ENOENT; return NULL; } p->status = 1; return p; }