From 59e6cc3fa7b629ba27f8cc7132add8455b466b7d Mon Sep 17 00:00:00 2001 From: nishi Date: Fri, 26 Jan 2024 12:27:54 +0000 Subject: [PATCH] redirect support git-svn-id: file:///raid/svn-main/nishi-libw3/trunk@90 d27a3e52-49c5-7645-884c-6793ebffc270 --- Example/interactive/interactive.c | 17 +++++++++++------ Library/Core.c | 19 +++++++++++++++++++ Library/HTTP.c | 28 ++++++++++++++++++++++++++++ Library/URL.c | 2 +- Library/Util.c | 30 ++++++++++++++++++++++++++++++ Library/W3Core.h | 2 ++ Library/W3HTTP.h | 2 ++ Library/W3Util.h | 2 ++ Makefile | 8 +++++++- W3Version.h.p | 2 +- 10 files changed, 103 insertions(+), 9 deletions(-) diff --git a/Example/interactive/interactive.c b/Example/interactive/interactive.c index c7a65cd..2c3c906 100644 --- a/Example/interactive/interactive.c +++ b/Example/interactive/interactive.c @@ -5,6 +5,8 @@ */ #include +#include + #include #include /* It has some useful functions, you know */ @@ -19,13 +21,14 @@ char* databuf; int datalen; void status_handler(struct W3* w3, int status) { printf("Response code: %d\n", status); } +void header_handler(struct W3* w3, char* key, char* value) { printf("Header: %s: %s\n", key, value); } void data_handler(struct W3* w3, char* data, size_t size) { - if(databuf == NULL){ + if(databuf == NULL) { databuf = malloc(size); datalen = size; memcpy(databuf, data, size); - }else{ + } else { char* oldbuf = databuf; databuf = malloc(datalen + size); memcpy(databuf, oldbuf, datalen); @@ -40,23 +43,25 @@ void access_site(const char* url) { if(u != NULL) { struct W3* w3 = W3_Create(u->protocol, u->host, u->port); if(w3 != NULL) { - if(databuf != NULL){ + if(databuf != NULL) { free(databuf); } databuf = NULL; datalen = 0; W3_Set_Method(w3, "GET"); W3_Set_Path(w3, u->path); + W3_Enable_Redirect(w3); W3_On(w3, "status", (void*)status_handler); + W3_On(w3, "header", (void*)header_handler); W3_On(w3, "data", (void*)data_handler); W3_Send_Request(w3); W3_Free(w3); printf("%d bytes\n", datalen); - }else{ + } else { fprintf(stderr, "Failed to connect\n"); } W3_Free_URL(u); - }else{ + } else { fprintf(stderr, "Failed to parse\n"); } } @@ -110,7 +115,7 @@ int main(int argc, char** argv) { acc = false; break; case 'p': - if(acc){ + if(acc) { write(1, databuf, datalen); } break; diff --git a/Library/Core.c b/Library/Core.c index 4dc7159..d04569d 100644 --- a/Library/Core.c +++ b/Library/Core.c @@ -50,6 +50,7 @@ struct W3* W3_Create(const char* protocol, const char* hostname, int port) { if(strcmp(protocol, "https") == 0) { ssl = true; } + w3->props = NULL; w3->method = NULL; w3->path = NULL; w3->events = NULL; @@ -190,10 +191,28 @@ void W3_Free(struct W3* w3) { for(i = 0; w3->headers[i] != 0; i++) free(w3->headers[i]); free(w3->headers); } + if(w3->props != NULL) { + int i; + for(i = 0; w3->props[i] != 0; i++) free(w3->props[i]); + free(w3->props); + } if(w3->events != NULL) { int i; for(i = 0; w3->events[i] != 0; i += 2) free(w3->events[i]); free(w3->events); } + W3_Disconnect(w3); free(w3); } + +void W3_Disconnect(struct W3* w3) { +#ifdef SSL_SUPPORT + if(w3->ssl != NULL) { + SSL_shutdown(w3->ssl); + SSL_CTX_free(w3->ssl_ctx); + SSL_free(w3->ssl); + w3->ssl = NULL; + } +#endif + if(w3->sock != -1) close(w3->sock); +} diff --git a/Library/HTTP.c b/Library/HTTP.c index f4166e5..5a7848c 100644 --- a/Library/HTTP.c +++ b/Library/HTTP.c @@ -3,6 +3,7 @@ #include "W3Core.h" #include "W3Util.h" +#include "W3URL.h" #include #include @@ -75,6 +76,7 @@ void __W3_HTTP_Request(struct W3* w3) { bool breakchunk = false; int chunksize; size_t allsize = -1; + char* redir = NULL; while(true) { int l = __W3_Auto_Read(w3, buf, w3->readsize); if(l <= 0) break; @@ -153,6 +155,9 @@ void __W3_HTTP_Request(struct W3* w3) { chunked = true; } else if(strcasecmp(data, "content-length") == 0) { allsize = atoi(data + k + 1); + } else if(strcasecmp(data, "location") == 0) { + if(redir != NULL) free(redir); + redir = __W3_Strdup(data + k + 1); } } break; @@ -249,4 +254,27 @@ void __W3_HTTP_Request(struct W3* w3) { free(buf); if(chunklen != NULL) free(chunklen); if(chunk != NULL) free(chunk); + if(redir != NULL && __W3_Have_Prop(w3, "HTTP_REDIRECT")){ + W3_Disconnect(w3); + struct W3URL* u = W3_Parse_URL(redir); + if(u != NULL){ + w3->sock = __W3_DNS_Connect(u->host, strcmp(u->protocol, "https") == 0 ? true : false, u->port +#ifdef SSL_SUPPORT + , + &w3->ssl, &w3->ssl_ctx +#endif + ); + free(w3->protocol); + w3->protocol = __W3_Strdup(u->protocol); + + free(w3->hostname); + w3->hostname = __W3_Strdup(u->host); + W3_Set_Path(w3, u->path); + W3_Free_URL(u); + W3_Send_Request(w3); + } + } + if(redir != NULL) free(redir); } + +void W3_Enable_Redirect(struct W3* w3) { __W3_Add_Prop(w3, "HTTP_REDIRECT"); } diff --git a/Library/URL.c b/Library/URL.c index 48b1f40..21767d2 100644 --- a/Library/URL.c +++ b/Library/URL.c @@ -75,7 +75,7 @@ struct W3URL* W3_Parse_URL(const char* _url) { __W3_Debug("URL", str); free(str); } - }else{ + } else { W3_Free_URL(r); r = NULL; } diff --git a/Library/Util.c b/Library/Util.c index 4d0e92f..d0297c2 100644 --- a/Library/Util.c +++ b/Library/Util.c @@ -109,3 +109,33 @@ char* __W3_Get_Platform(void) { return __W3_Concat3(un.sysname, "/", un.release); #endif } + +bool __W3_Have_Prop(struct W3* w3, const char* name) { + if(w3->props == NULL) return false; + int i; + for(i = 0; w3->props[i] != NULL; i++) { + if(strcmp(w3->props[i], name) == 0) return true; + } + return false; +} + +void __W3_Add_Prop(struct W3* w3, const char* name) { + char* str = __W3_Concat3("Adding a prop `", name, "`"); + __W3_Debug("Prop", str); + free(str); + int len = 0; + if(w3->props == NULL) { + w3->props = malloc(sizeof(*w3->props) * 2); + } else { + char** oldprops = w3->props; + for(len = 0; oldprops[len] != NULL; len++) + ; + w3->props = malloc(sizeof(*w3->props) * (len + 2)); + for(len = 0; oldprops[len] != NULL; len++) { + w3->props[len] = oldprops[len]; + } + free(oldprops); + } + w3->props[len] = __W3_Strdup(name); + w3->props[len + 1] = NULL; +} diff --git a/Library/W3Core.h b/Library/W3Core.h index 338fc7d..3eb67f2 100644 --- a/Library/W3Core.h +++ b/Library/W3Core.h @@ -23,6 +23,7 @@ struct W3 { char* data; /* As you can read from its name */ size_t size; /* Size of the data */ size_t readsize; /* Read buffer size, default is 512 */ + char** props; /* Properties */ #ifdef SSL_SUPPORT void* ssl; /* Actually SSL*, NULL if no SSL */ void* ssl_ctx; /* Actually SSL_CTX* */ @@ -38,6 +39,7 @@ void W3_Send_Request(struct W3* w3); /* Send the request */ void W3_Set_Header(struct W3* w3, const char* key, const char* value); /* Set the header */ void W3_Free(struct W3* w3); /* Free the struct */ void W3_On(struct W3* w3, const char* eventname, void* func); /* Set Handlers */ +void W3_Disconnect(struct W3* w3); /* Disconnect */ void W3_Set_Data(struct W3* w3, char* data, size_t size); /* Send the data - LibW3 won't free the data */ void W3_Set_Read_Size(struct W3* w3, size_t size); /* Change the read buffer size */ diff --git a/Library/W3HTTP.h b/Library/W3HTTP.h index 2000259..a915839 100644 --- a/Library/W3HTTP.h +++ b/Library/W3HTTP.h @@ -7,7 +7,9 @@ extern "C" { #endif #include "W3Core.h" + void __W3_HTTP_Request(struct W3* w3); +void W3_Enable_Redirect(struct W3* w3); #ifdef __cplusplus } diff --git a/Library/W3Util.h b/Library/W3Util.h index 500b24b..4bcadde 100644 --- a/Library/W3Util.h +++ b/Library/W3Util.h @@ -17,6 +17,8 @@ char* __W3_Strdup(const char* str); unsigned long __W3_Auto_Write(struct W3* w3, char* data, unsigned long length); unsigned long __W3_Auto_Read(struct W3* w3, char* data, unsigned long length); bool __W3_Have_Header(struct W3* w3, const char* name); +bool __W3_Have_Prop(struct W3* w3, const char* name); +void __W3_Add_Prop(struct W3* w3, const char* name); void* __W3_Get_Event(struct W3* w3, const char* eventname); char* __W3_Get_Platform(void); diff --git a/Makefile b/Makefile index 829928b..2925248 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,18 @@ # $Id$ include config.mk +ifeq ($(shell uname -s),SunOS) +GREP = ggrep +else +GREP = grep +endif + CC := cc CFLAGS := -g -std=c99 -fPIC -D_BSD_SOURCE LDFLAGS := LIBS := PREFIX := /usr/local -VERSION = $(shell cat Library/W3Version.h | grep -m 1 LIBW3_VERSION | sed -E "s/.+\"([^\"]+)\".+/\1/g")$(shell cat Library/W3Version.h | grep -A 1 -Eo "LIBW3_VERSION" | tail -n1 | grep -Eo "W") +VERSION = $(shell cat Library/W3Version.h | $(GREP) -m 1 LIBW3_VERSION | sed -E "s/.+\"([^\"]+)\".+/\1/g")$(shell cat Library/W3Version.h | grep -A 1 -Eo "LIBW3_VERSION" | tail -n1 | grep -Eo "W") ifeq ($(SSL),YES) diff --git a/W3Version.h.p b/W3Version.h.p index b835f8e..26fe868 100644 --- a/W3Version.h.p +++ b/W3Version.h.p @@ -6,7 +6,7 @@ extern "C" { #endif -#define LIBW3_VERSION "1.4A" \ +#define LIBW3_VERSION "1.5" \ SUFFIX #ifdef __cplusplus -- 2.43.0