lua-glue.c (3493B)
1 #include <stdlib.h> 2 #include <string.h> 3 4 #include <lua.h> 5 #include <lualib.h> 6 #include <lauxlib.h> 7 #include "fetch.h" 8 9 /* 10 FIXME: "By default libfetch allows TLSv1 and newer when negotiating 11 the connecting with the remote peer. You can change this behavior 12 by setting the SSL_NO_TLS1, SSL_NO_TLS1_1 and SSL_NO_TLS1_2 13 environment variables to disable TLS 1.0, 1.1 and 1.2 respectively." 14 */ 15 16 int lp_error(lua_State *L, int code, char *message) { 17 lua_pushnil(L); 18 lua_pushinteger(L, code); 19 lua_pushlstring(L, message, strlen(message)); 20 return 3; 21 } 22 23 int lp_fetched(lua_State *L, FXRETTYPE fp, struct url_stat *stat) { 24 size_t bytes_read = 0; 25 char * content = 0; 26 if(stat->size > 0) { 27 content = (char *) malloc(stat->size); 28 es_read(fp, content, stat->size, &bytes_read); 29 30 if(bytes_read != stat->size) { 31 lp_error(L, -1, "bytes read does not match content-length"); 32 } 33 } else { 34 /* no content-length header */ 35 int block_size = 128; 36 int buf_size = block_size; 37 size_t bytes_read_block; 38 do { 39 content = (char *) realloc(content, buf_size); 40 es_read(fp, content + bytes_read, block_size, &bytes_read_block); 41 bytes_read += bytes_read_block; 42 buf_size += block_size; 43 } while(bytes_read_block > 0); 44 } 45 46 lua_pushlstring(L, (const char *) content, bytes_read); 47 lua_newtable(L); 48 lua_pushliteral(L, "last-modified"); 49 lua_pushinteger(L, stat->mtime); 50 lua_settable(L, -3); 51 /* free(content) ? */ 52 return 2; 53 } 54 55 int lp_fetch(lua_State *L) { 56 const char * url_string = luaL_checkstring(L, 1); 57 const char * flags = luaL_optstring(L, 2, ""); 58 time_t if_modified_since = luaL_optinteger(L, 3, 0); 59 60 struct url *url = fetchParseURL(url_string); 61 if(url == NULL) { 62 return lp_error(L, -1, "url not parseable"); 63 } 64 url->ims_time = if_modified_since; 65 struct url_stat stat; 66 67 FXRETTYPE fp = fetchXGet(url, &stat, flags); 68 fetchFreeURL(url); 69 if(fp == NULL) { 70 return lp_error(L, fetchLastErrCode, fetchLastErrString); 71 } 72 return lp_fetched(L, fp, &stat); 73 } 74 75 /* http_request_body seems to be semi-private in libfetch, but if using 76 * only the fetch* functions there's no way to send an http request 77 * with a body, so we use it anyway 78 */ 79 extern FXRETTYPE 80 http_request_body(struct url *URL, const char *op, struct url_stat *us, 81 struct url *purl, const char *flags, const char *content_type, 82 const char *body); 83 84 int lp_request(lua_State *L) { 85 const char * request_method = luaL_checkstring(L, 1); 86 const char * url_string = luaL_checkstring(L, 2); 87 const char * flags = luaL_optstring(L, 3, ""); 88 time_t if_modified_since = luaL_optinteger(L, 4, 0); 89 const char * content_type = lua_tostring(L, 5); 90 const char * body = lua_tostring(L, 6); 91 92 struct url *url = fetchParseURL(url_string); 93 if(url == NULL) { 94 return lp_error(L, -1, "url not parseable"); 95 } 96 url->ims_time = if_modified_since; 97 struct url_stat stat; 98 99 FXRETTYPE fp = http_request_body(url, 100 request_method, 101 &stat, 102 NULL, /* no proxy */ 103 flags, 104 content_type, 105 body); 106 fetchFreeURL(url); 107 if(fp == NULL) { 108 return lp_error(L, fetchLastErrCode, fetchLastErrString); 109 } 110 return lp_fetched(L, fp, &stat); 111 } 112 113 static const struct luaL_Reg funcs [] = { 114 {"fetch", lp_fetch}, 115 {"request", lp_request}, 116 {NULL, NULL} /* sentinel */ 117 }; 118 119 120 int luaopen_fetch (lua_State *L) { 121 luaL_newlib(L, funcs); 122 return 1; 123 }