Refactor code into utils, mfapi and mfshell

- utils is the low level library used by the others
 - mfapi uses utils and implements the api and some wrappers
 - mfshell uses mfapi and utils to provide a shell
This commit is contained in:
josch
2014-09-18 09:11:00 +02:00
parent 2d6a79062a
commit ef3b2aa844
57 changed files with 767 additions and 1345 deletions

233
utils/http.c Normal file
View File

@@ -0,0 +1,233 @@
/*
* Copyright (C) 2014 Johannes Schauer <j.schauer@email.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <stdbool.h>
#include "http.h"
static int http_progress_cb(void *user_ptr, double dltotal, double dlnow, double ultotal, double ulnow);
static size_t http_read_buf_cb(char *data, size_t size, size_t nmemb, void *user_ptr);
static size_t http_write_buf_cb(char *data, size_t size, size_t nmemb, void *user_ptr);
static size_t http_write_file_cb(char *data, size_t size, size_t nmemb, void *user_ptr);
struct _http_s
{
CURL *curl_handle;
char *write_buf;
size_t write_buf_len;
double ul_len;
double ul_now;
double dl_len;
double dl_now;
bool show_progress;
char error_buf[CURL_ERROR_SIZE];
FILE *stream;
};
/*
* This set of functions is made such that the http_t struct and the curl
* handle it stores can be reused for multiple operations
*
* We do not use a single global instance because mediafire does not support
* keep-alive anyways.
*/
http_t*
http_create(void)
{
http_t *conn;
CURL *curl_handle;
curl_handle = curl_easy_init();
if(curl_handle == NULL) return NULL;
conn = (http_t*)calloc(1,sizeof(http_t));
conn->curl_handle = curl_handle;
conn->show_progress = false;
curl_easy_setopt(conn->curl_handle, CURLOPT_NOPROGRESS,0);
curl_easy_setopt(conn->curl_handle, CURLOPT_PROGRESSFUNCTION, http_progress_cb);
curl_easy_setopt(conn->curl_handle, CURLOPT_PROGRESSDATA, (void *)conn);
curl_easy_setopt(conn->curl_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(conn->curl_handle, CURLOPT_SSLENGINE, NULL);
curl_easy_setopt(conn->curl_handle, CURLOPT_SSLENGINE_DEFAULT, 1L);
curl_easy_setopt(conn->curl_handle, CURLOPT_ERRORBUFFER, conn->error_buf);
return conn;
}
json_t *
http_parse_buf_json(http_t* conn, size_t flags, json_error_t *error)
{
return json_loadb(conn->write_buf, conn->write_buf_len, flags, error);
}
void
http_destroy(http_t* conn)
{
curl_easy_cleanup(conn->curl_handle);
free(conn->write_buf);
free(conn);
}
static int http_progress_cb(void *user_ptr, double dltotal, double dlnow,
double ultotal, double ulnow)
{
http_t *conn;
if (user_ptr == NULL) return 0;
conn = (http_t *)user_ptr;
conn->ul_len = ultotal;
conn->ul_now = ulnow;
conn->dl_len = dltotal;
conn->dl_now = dlnow;
return 0;
}
int
http_get_buf(http_t *conn, const char *url, int (*data_handler)(http_t *conn, void *data), void *data)
{
int retval;
curl_easy_reset(conn->curl_handle);
curl_easy_setopt(conn->curl_handle, CURLOPT_URL, url);
curl_easy_setopt(conn->curl_handle, CURLOPT_READFUNCTION, http_read_buf_cb);
curl_easy_setopt(conn->curl_handle, CURLOPT_READDATA, (void*)conn);
curl_easy_setopt(conn->curl_handle, CURLOPT_WRITEFUNCTION, http_write_buf_cb);
curl_easy_setopt(conn->curl_handle, CURLOPT_WRITEDATA, (void*)conn);
//fprintf(stderr, "GET: %s\n", url);
retval = curl_easy_perform(conn->curl_handle);
if(retval != CURLE_OK) {
fprintf(stderr, "error curl_easy_perform %s\n\r", conn->error_buf);
return retval;
}
if (data_handler != NULL)
retval = data_handler(conn, data);
conn->write_buf_len = 0;
return retval;
}
static size_t
http_read_buf_cb(char *data, size_t size, size_t nmemb, void *user_ptr)
{
http_t *conn;
size_t data_len;
if (user_ptr == NULL) return 0;
conn = (http_t*)user_ptr;
data_len = size*nmemb;
if (data_len > 0) {
fprintf(stderr, "Not implemented");
exit(1);
}
return 0;
}
static size_t
http_write_buf_cb(char *data, size_t size, size_t nmemb, void *user_ptr)
{
http_t *conn;
size_t data_len;
if (user_ptr == NULL) return 0;
conn = (http_t*)user_ptr;
data_len = size*nmemb;
if (data_len > 0) {
//fwrite(data, size, nmemb, stderr);
conn->write_buf = (char *)realloc(conn->write_buf,
conn->write_buf_len + data_len);
memcpy(conn->write_buf + conn->write_buf_len, data, data_len);
conn->write_buf_len += data_len;
}
return data_len;
}
int
http_post_buf(http_t *conn, const char *url, const char *post_args, int (*data_handler)(http_t *conn, void *data), void *data)
{
int retval;
curl_easy_reset(conn->curl_handle);
curl_easy_setopt(conn->curl_handle, CURLOPT_URL, url);
curl_easy_setopt(conn->curl_handle, CURLOPT_READFUNCTION, http_read_buf_cb);
curl_easy_setopt(conn->curl_handle, CURLOPT_READDATA, (void*)conn);
curl_easy_setopt(conn->curl_handle, CURLOPT_WRITEFUNCTION, http_write_buf_cb);
curl_easy_setopt(conn->curl_handle, CURLOPT_WRITEDATA, (void*)conn);
curl_easy_setopt(conn->curl_handle, CURLOPT_POSTFIELDS, post_args);
retval = curl_easy_perform(conn->curl_handle);
if(retval != CURLE_OK) {
fprintf(stderr, "error curl_easy_perform %s\n\r", conn->error_buf);
return retval;
}
if (data_handler != NULL)
retval = data_handler(conn, data);
conn->write_buf_len = 0;
return retval;
}
int
http_get_file(http_t *conn, const char *url, const char *path)
{
int retval;
curl_easy_reset(conn->curl_handle);
curl_easy_setopt(conn->curl_handle, CURLOPT_URL, url);
curl_easy_setopt(conn->curl_handle, CURLOPT_READFUNCTION, http_read_buf_cb);
curl_easy_setopt(conn->curl_handle, CURLOPT_READDATA, (void*)conn);
curl_easy_setopt(conn->curl_handle, CURLOPT_WRITEFUNCTION, http_write_file_cb);
curl_easy_setopt(conn->curl_handle, CURLOPT_WRITEDATA, (void*)conn);
// FIXME: handle fopen() return value
conn->stream = fopen(path, "w+");
retval = curl_easy_perform(conn->curl_handle);
fclose(conn->stream);
if(retval != CURLE_OK) {
fprintf(stderr, "error curl_easy_perform %s\n\r", conn->error_buf);
return retval;
}
return retval;
}
static size_t
http_write_file_cb(char *data, size_t size, size_t nmemb, void *user_ptr)
{
http_t *conn;
if (user_ptr == NULL) return 0;
conn = (http_t*)user_ptr;
fwrite(data, size, nmemb, conn->stream);
fprintf(stderr, "\r %.0f / %.0f", conn->dl_now, conn->dl_len);
}
int
http_post_file(http_t *conn, const char *url, const char *post_args, FILE *fd)
{
}

37
utils/http.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2014 Johannes Schauer <j.schauer@email.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by█
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _MFSHELL_HTTP_H_
#define _MFSHELL_HTTP_H_
#include <jansson.h>
typedef struct _http_s http_t;
struct _http_s;
http_t* http_create(void);
void http_destroy(http_t* conn);
int http_get_buf(http_t *conn, const char *url, int (*data_handler)(http_t *conn, void *data), void *data);
int http_post_buf(http_t *conn, const char *url, const char *post_args, int (*data_handler)(http_t *conn, void *data), void *data);
int http_get_file(http_t *conn, const char *url, const char *path);
int http_post_file(http_t *conn, const char *url, const char *post_args, FILE *fd);
json_t *http_parse_buf_json(http_t* conn, size_t flags, json_error_t *error);
#endif

106
utils/json.c Normal file
View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2013 Bryan Christ <bryan.christ@mediafire.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdlib.h>
#include <string.h>
#include "json.h"
#include "stringv.h"
json_t*
json_object_by_path(json_t *start,const char *path)
{
char **path_nodes;
char **curr;
json_t *node = NULL;
json_t *data = NULL;
if(start == NULL) return NULL;
if(path == NULL) return NULL;
path_nodes = stringv_split((char*)path,"/",10);
if(path_nodes == NULL) return NULL;
curr = path_nodes;
node = start;
while(curr != NULL)
{
if(*curr == NULL) break;
node = json_object_get(node,*curr);
if(node == NULL) break;
if(!json_is_object(node))
{
stringv_free(path_nodes,STRINGV_FREE_ALL);
return NULL;
}
curr++;
data = node;
}
stringv_free(path_nodes,STRINGV_FREE_ALL);
return data;
}
// fix a path with leading slashes
/*
while(strlen(path) > 0)
{
if(*path[0] == '\')
{
path++;
continue;
}
len = strlen(path);
buffer = (char*)calloc(len + 1,sizeof(char));
strncpy(buffer,path,len);
}
// something went horribly wrong
if(buffer == NULL) return NULL;
pos = buffer[strlen(buffer) - 1];
// fix a path with trailing slashes
while(pos != buffer)
{
if(pos[0] == '/')
{
pos[0] = '\0';
pos--;
continue;
}
break;
}
// something else went horribly wrong
if(pos == buffer)
{
free(buffer);
return NULL;
}
*/

29
utils/json.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2013 Bryan Christ <bryan.christ@mediafire.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _MFSHELL_JSON_H_
#define _MFSHELL_JSON_H_
#include <jansson.h>
json_t* json_object_by_path(json_t *start,const char *path);
#endif

259
utils/strings.c Normal file
View File

@@ -0,0 +1,259 @@
/*
* Copyright (C) 2013 Bryan Christ <bryan.christ@mediafire.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include "strings.h"
#include "stringv.h"
char*
strdup_printf(char* fmt, ...)
{
// Good for glibc 2.1 and above. Fedora5 is 2.4.
char *ret_str = NULL;
va_list ap;
int bytes_to_allocate;
va_start(ap, fmt);
bytes_to_allocate = vsnprintf(ret_str, 0, fmt, ap);
va_end(ap);
// Add one for '\0'
bytes_to_allocate++;
ret_str = (char*)malloc(bytes_to_allocate * sizeof(char));
va_start(ap, fmt);
bytes_to_allocate = vsnprintf(ret_str, bytes_to_allocate, fmt, ap);
va_end(ap);
return ret_str;
}
char*
strdup_join(char *string1,char *string2)
{
char *new_string;
size_t string1_len;
size_t string2_len;
if(string1 == NULL || string2 == NULL) return NULL;
string1_len = strlen(string1);
string2_len = strlen(string2);
new_string = (char*)malloc(string1_len + string2_len + 1);
strncpy(new_string,string1,string1_len);
strncat(new_string,string2,string2_len);
new_string[string1_len + string2_len] = '\0';
return new_string;
}
char*
strdup_subst(char *string,char *token,char *subst,int max)
{
size_t string_len = 0;
size_t subst_len = 0;
size_t token_len = 0;
size_t total_len = 0;
size_t copy_len = 0;
size_t token_count;
char *str_new = NULL;
char **vectors;
char **rewind;
if(string == NULL) return NULL;
if(token == NULL || subst == NULL) return NULL;
string_len = strlen(string);
token_len = strlen(token);
// return on conditions that we could never handle.
if(token_len > string_len) return NULL;
if(token[0] == '\0') return NULL;
vectors = stringv_find(string,token,max);
if(vectors == NULL) return NULL;
rewind = vectors;
// count the number of tokens found in the string
token_count = stringv_len(vectors);
if(token_count > max) token_count = max;
// start with the original string size;
total_len = string_len;
// subtract the total number of token chars to be removed
total_len -= (token_len * token_count);
// add back the total number of subst chars to be inserted
total_len += (subst_len * token_count);
str_new = (char*)malloc((total_len + 1) * sizeof(char));
str_new[0] = '\0';
while(*vectors != NULL)
{
// calculate distance to the next token from current position
copy_len = *vectors - string;
if(copy_len > 0)
{
strncat(str_new,string,copy_len);
string += copy_len;
// when total_len == 0 the process is complete
total_len -= copy_len;
}
strncat(str_new,token,token_len);
// when total_len == 0 the process is complete
total_len -= token_len;
vectors++;
}
// might have one more copy operation to complete
if(total_len > 0)
{
strcat(str_new,string);
}
// todo: can't free vectors directly cuz it was incremented
free(rewind);
return str_new;
}
void
string_chomp(char *string)
{
size_t len;
char *pos;
if(string == NULL) return;
len = strlen(string);
if(len == 0) return;
pos = &string[len - 1];
while(isspace((int)*pos) != 0)
{
*pos = '\0';
pos--;
}
return;
}
/*
void
string_strip_head(char *string,int c)
{
int count = 0;
int len;
char *pos;
if(string == NULL) return;
len = strlen(string);
if(len == 0) return;
pos = string;
while(count < len)
{
if(c <= 0)
{
if(isaspace((char)pos[0])
{
pos++;
count++;
continue;
}
break;
}
if(
// fix a path with leading slashes
while(strlen(string) > 0)
{
if(c > 0)
{
if(string[0] == c)
{
if(string[0] == (c)
{
string++;
continue;
}
len = strlen(path);
buffer = (char*)calloc(len + 1,sizeof(char));
strncpy(buffer,path,len);
}
*/
/*
A negative value shifts the string left, while a positive value
shifts the string right. The vacuum-space is zero filled.
*/
/*
void
string_shift(char *string,ssize_t vector)
{
char *pos;
ssize_t len;
ssize_t i;
if(string == NULL) return;
len = strlen(string);
if(len <= ABSINT(vector)) return;
// shift left
if(vector < 0)
{
pos = string + (ABSINT(vector));
strcpy(string,pos);
string[len - ABSINT(vector) + 1] = '\0';
return;
}
}
*/

37
utils/strings.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2013 Bryan Christ <bryan.christ@mediafire.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _STR_TOOLS_H_
#define _STR_TOOLS_H_
#include <stdint.h>
char* strdup_printf(char* fmt, ...);
char* strdup_join(char *string1,char *string2);
char* strdup_subst(char *string,char *str_old,char *str_new,int max);
void string_chomp(char *string);
// void string_strip_head(char *string,char c);
// void string_strip_tail(char *string,char c);
#endif

176
utils/stringv.c Normal file
View File

@@ -0,0 +1,176 @@
/*
* Copyright (C) 2013 Bryan Christ <bryan.christ@mediafire.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "stringv.h"
size_t
stringv_len(char **array)
{
size_t count = 0;
char **pos;
if(array == NULL) return 0;
pos = array;
while(pos[0] != NULL)
{
pos++;
count++;
}
return count;
}
void
stringv_free(char **array,int b_free)
{
char **pos;
if(array == NULL) return;
pos = array;
while((*pos) != NULL)
{
free(*pos);
++pos;
}
if(b_free == STRINGV_FREE_ALL) free(array);
return;
}
char**
stringv_copy(char **array)
{
uint32_t array_len;
char **array_pos;
char **dup_array;
char **dup_pos;
if(array == NULL) return (char**)NULL;
array_pos = array;
array_len = stringv_len(array);
if(array_len > UINT32_MAX - 1) array_len = UINT32_MAX -1;
dup_array = (char**)calloc(array_len,sizeof(char*));
dup_pos = dup_array;
while((*array_pos) != NULL)
{
*dup_pos = strdup((const char*)*array_pos);
array_pos++;
dup_pos++;
}
return dup_array;
}
char**
stringv_find(char *string,char *token,int limit)
{
char **results = NULL;
char *pos = NULL;
int count = 0;
if(string == NULL) return (char**)NULL;
if(token == NULL) return (char**)NULL;
if(limit == 0) return (char**)NULL;
pos = string;
if(strlen(token) > strlen(string)) return (char**)NULL;
while(count != limit)
{
pos = strstr(pos,token);
if(pos == NULL) break;
count++;
results = (char**)realloc((void*)results,sizeof(char*) * count + 1);
results[count - 1] = pos;
}
if(count == 0) return (char**)NULL;
results[count] = (char*)NULL;
return results;
}
char**
stringv_split(char *string,char *token,int limit)
{
char **results = NULL;
char *curr = NULL;
char *next = NULL;
int count = 0;
int len;
size_t copy_len = 0;
if(string == NULL) return (char**)NULL;
if(token == NULL) return (char**)NULL;
if(limit == 0) return (char**)NULL;
len = strlen(string);
if(strlen(token) > len) return (char**)NULL;
curr = string;
do
{
// alloc space for current item plus NULL vector terminator
results = (char**)realloc(results,sizeof(char*) * (count + 2));
// find the next occurrence
next = strstr(curr,token);
if(next != NULL)
copy_len = next - curr;
else
copy_len = strlen(curr);
results[count] = (char*)calloc(copy_len + 1,sizeof(char));
memcpy(results[count],curr,copy_len);
count++;
if(next == NULL) break;
curr = next;
curr++;
}
while(count < limit);
results[count] = NULL;
return results;
}

44
utils/stringv.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2013 Bryan Christ <bryan.christ@mediafire.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2, as published by
* the Free Software Foundation.
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _STRING_V_H_
#define _STRING_V_H_
#include <stdint.h>
#define STRINGV_FREE_ALL 1
// count number of strings in a NULL in a string vector
size_t stringv_len(char **array);
// free all of the strings in a vector and optionally the vector pointer
void stringv_free(char **array,int b_free);
// deep copy of string vector. returns a new vector pointer
char** stringv_copy(char **array);
// returns a NULL terminated vector array to every location 'token' is found
char** stringv_find(char *string,char *token,int limit);
// returns a NULL terminated vector array of items delimited by 'token'
char** stringv_split(char *string,char *token,int limit);
#endif