📄 http.c
字号:
/******************************************************************************* * * http.c * * Provides the means for communicating with remote servers via http * * Version info etc. * * Cheetah Web Browser * Copyright (C) 2001 Garett Spencley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *******************************************************************************/#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <netdb.h>#include <netinet/in.h>#include <unistd.h>#include "http.h"#include "error.h"#include "cheetah.h"#include "debug.h"int sock_fd;int sock_fd_open;int connected;char *hostname;int http_errno;int http_connection_open(void){ return connected;}/* * http_connect() - establishes a remote http connection to * host. Returns 0 on success. Returns -1 on failure and * http_errno is set appropriately */int http_connect(char *host, unsigned short port, GuiMessage *msg){ struct hostent *hp; struct sockaddr_in sin; /* Bail out if we're already connected */ if(connected) return HTTP_ALREADY_CONNECTED; /* Set the hostname */ hostname = strdup(host); if(!hostname) { http_errno = HTTP_NOMEM; return -1; } snprintf(msg->text, 255, "Looking up host %s...", hostname); msg->text[255] = 0; msg->seq++; /* Resolve the host */ hp = gethostbyname(hostname); if(!hp) hp = gethostbyaddr(hostname, strlen(hostname), AF_INET); if(!hp) { http_errno = HTTP_RESOLV; return -1; } sin.sin_family = hp->h_addrtype; memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); sin.sin_port = htons(port); memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); strcpy(msg->text, "Connecting..."); msg->seq++; if((sock_fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { http_errno = HTTP_CONNECT; return -1; } if(connect(sock_fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) { close(sock_fd); http_errno = HTTP_CONNECT; return -1; } sock_fd_open = 1; connected = 1; snprintf(msg->text, 255, "Connected to %s", hostname); msg->text[255] = 0; msg->seq++; return 0;}/* * http_close() - closes a http connection */int http_close(){ if(!connected) return 0; connected = 0; free(hostname); if(sock_fd_open) { close(sock_fd); sock_fd_open = 0; } return 0;}/* * http_nget() - retrive only size bytes from file storing the * result in buffer */int http_nget(char *buffer, FILE *file, size_t size, GuiMessage *msg){ int counter; int c; if(!buffer || !file) { fprintf(stderr, "http_nget: Received NULL arguments.\n"); return -1; } /* char by char instead of fgets() for status * reporting .... */ counter = 0; debug_print("Transfering %d bytes", size); while(counter != size) { c = fgetc(file); if(c == EOF) break; buffer[counter++] = c; if (((counter % 512) == 0) && (size > 0)) { snprintf(msg->text, 255, "Received %d of %d bytes (%d%%)", counter, size, ((counter * 100) / size)); msg->text[255] = 0; msg->seq++; } }// buffer[counter] = 0; /*if (counter == size) { strcpy(msg->text, "Done."); msg->seq++; }*/ return 0;}/* * get_all() - Retrieve the entire contents of file and * return it in a dynamically allocated buffer */char *get_all(FILE *file, int *bytes, GuiMessage *msg){ char *result; int c, counter; int bufsize; bufsize = 2048; result = (char *)malloc(sizeof(char) * bufsize); if(!result) return NULL; counter = 0; while((c = fgetc(file)) != EOF) { if(counter >= bufsize) { bufsize += 256; result = (char *)realloc(result, sizeof(char) * bufsize); if(!result) return NULL; } result[counter++] = c; if ( (counter % 512) == 0 ) { snprintf(msg->text, 255, "Received %d bytes", counter); msg->text[255] = 0; msg->seq++; } }// result[counter] = 0;/* strcpy(msg->text, "Done."); msg->seq++; */ *bytes = counter; return result;}void http_file_free(HttpFile *file){ g_return_if_fail(file != NULL && file->data != NULL && file->content_type != NULL); free(file->data); free(file->content_type); free(file);}/* * http_get() - retrieves remote document from server * storing it in a buffer_t. You must call http_connect() * before using this function */HttpFile *http_get(char *path, GuiMessage *msg){ FILE *sock; char buf[255]; char content_type[256]; int size; HttpFile *result; /* Check for open connection */ if(!connected) { http_errno = HTTP_ALREADY_CONNECTED; return NULL; } if(!sock_fd_open) { http_errno = HTTP_NOT_CONNECTED; return NULL; } /* Re-open the socket as a FILE stream */ sock = fdopen(sock_fd, "r+"); if(!sock) { close(sock_fd); http_errno = HTTP_FILE_DESC; return NULL; } sock_fd_open = 0; /* Send GET command */ strcpy(msg->text,"Politely asking for document"); msg->seq++; fprintf(sock, "GET %s HTTP/1.0\n", path); fprintf(sock, "User-Agent: Cheetah %s\n", CHEETAH_VERSION); fprintf(sock, "Connection: close\n"); fprintf(sock, "Host: %s\n\n", hostname); fflush(sock); /* Allocate the file structure */ result = (HttpFile *)malloc(sizeof(HttpFile)); if(!result) { http_errno = HTTP_NOMEM; return NULL; } /* Retrieve relevant headers. */ size = 0; while((fgets(buf, 255, sock))) { if(*buf == '\r' && buf[1] == '\n') break; sscanf(buf, "Content-Length: %d", &size); sscanf(buf, "Content-Type: %s", content_type); } if(strlen(content_type)) { result->content_type = strdup(content_type); if(!result->content_type) { http_errno = HTTP_NOMEM; free(result); return NULL; } } else result->content_type = strdup(""); if(size < 0) { fclose(sock); free(result); http_errno = HTTP_CONTENT_LENGTH; return NULL; } /* Create the buffer and fill it */ if(size == 0) { result->data = get_all(sock, &(result->bytes), msg); if(!result->data) { fclose(sock); free(result); http_errno = HTTP_NOMEM; return NULL; } } else { result->data = (char *)malloc(sizeof(char) * size); if(!result->data) { fclose(sock); free(result); http_errno = HTTP_NOMEM; return NULL; } if(http_nget(result->data, sock, size, msg) < 0) free(result); result->bytes = size; } fclose(sock); return result;}/* * http_perror() - prints msg followed by a ':' followed by the * error associated with http_errno (prints it to 'error()' function) */void http_perror(char *msg,char *dest){ char string[512]; int max_len; snprintf(string, 511, "%s: ", msg); string[511] = 0; max_len = 512 - strlen(msg); switch(http_errno) { case HTTP_ERROR_UNKOWN: strncat(string, "Unkown error.", max_len-1); string[max_len-1] = 0; break; case HTTP_ALREADY_CONNECTED: strncat(string, "Attempted to connect to remote host" "while already connected.", max_len-1); string[max_len-1] = 0; break; case HTTP_RESOLV: strncat(string, "Unable to resolve hostname.", max_len-1); string[max_len-1] = 0; break; case HTTP_CONNECT: strncat(string, "Unable to connect to remote host.", max_len-1); string[max_len-1] = 0; break; case HTTP_NOMEM: strncat(string, "Out of memory.", max_len-1); string[max_len-1] = 0; break; case HTTP_CONTENT_LENGTH: strncat(string, "Document contained an illegal Content-Length.", max_len-1); string[max_len-1] = 0; break; case HTTP_NOT_CONNECTED: strncat(string, "Attempted to retrieve remote document while not" "connected to remote server.", max_len-1); string[max_len-1] = 0; break; case HTTP_FILE_DESC: strncat(string, "Problem with socket file descriptor.", max_len-1); string[max_len-1] = 0; break; default: strncat(string, "Unkown error.", max_len-1); string[max_len-1] = 0; break; } if (dest==NULL) error(string); else strncpy(dest,string,255);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -