liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }