From b6189f1907e22aad1cda7ecf236529bd7b270734 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Sat, 4 Jun 2011 16:01:39 +0200 Subject: remove dependency on curl binary fb-upload is now called fb-helper which supports downloading and uploading Signed-off-by: Florian Pritz --- .gitignore | 4 +- Makefile | 18 ++--- fb-helper.c.in | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fb-upload.c.in | 237 ----------------------------------------------------- fb.in | 34 ++------ 5 files changed, 271 insertions(+), 274 deletions(-) create mode 100644 fb-helper.c.in delete mode 100644 fb-upload.c.in diff --git a/.gitignore b/.gitignore index ab9a34a..5afae78 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ dist fb.1 fb -fb-upload -fb-upload.c +fb-helper +fb-helper.c diff --git a/Makefile b/Makefile index e493b7b..de7fd1d 100644 --- a/Makefile +++ b/Makefile @@ -5,40 +5,40 @@ LIBDIR=/usr/lib CC=gcc CFLAGS=-O2 -std=c99 -Wall -Wextra -pedantic -all: fb.1 fb fb-upload +all: fb.1 fb fb-helper fb: fb.in @[ -n "$(VERSION)" ] || (echo "Error: version detection failed"; exit 1) sed 's|@VERSION@|$(VERSION)|; s|@LIBDIR@|$(LIBDIR)|' fb.in > fb chmod 755 fb -fb-upload.c: fb-upload.c.in - sed 's/@VERSION@/$(VERSION)/' fb-upload.c.in > fb-upload.c +fb-helper.c: fb-helper.c.in + sed 's/@VERSION@/$(VERSION)/' fb-helper.c.in > fb-helper.c -fb-upload: fb-upload.c - $(CC) $(CFLAGS) -lcurl -lm -o fb-upload fb-upload.c +fb-helper: fb-helper.c + $(CC) $(CFLAGS) -lcurl -lm -o fb-helper fb-helper.c fb.1: fb.pod pod2man -c "" fb.pod fb.1 clean: - rm -f fb.1 fb fb-upload.c fb-upload + rm -f fb.1 fb fb-helper.c fb-helper rm -rf dist install: all install -Dm755 fb $(DESTDIR)$(BINDIR)/fb - install -Dm755 fb-upload $(DESTDIR)$(LIBDIR)/fb-upload + install -Dm755 fb-helper $(DESTDIR)$(LIBDIR)/fb-helper install -Dm644 fb.1 $(DESTDIR)$(MANDIR)/man1/fb.1 uninstall: rm -f $(DESTDIR)$(BINDIR)/fb - rm -f $(DESTDIR)$(LIBDIR)/fb-upload + rm -f $(DESTDIR)$(LIBDIR)/fb-helper rm -f $(DESTDIR)$(MANDIR)/man1/fb.1 dist: all @[ -n "$(VERSION)" ] || (echo "Error: version detection failed"; exit 1) mkdir -p dist/fb-$(VERSION) - cp -a fb-upload.c{,.in} fb{,.in} fb.pod fb.1 COPYING Makefile dist/fb-$(VERSION) + cp -a fb-helper.c{,.in} fb{,.in} fb.pod fb.1 COPYING Makefile dist/fb-$(VERSION) sed -i 's/^VERSION:=.*$$/VERSION:="'$(VERSION)'"/' dist/fb-$(VERSION)/Makefile cd dist; tar -czf fb-$(VERSION).tar.gz fb-$(VERSION) diff --git a/fb-helper.c.in b/fb-helper.c.in new file mode 100644 index 0000000..2d92caa --- /dev/null +++ b/fb-helper.c.in @@ -0,0 +1,252 @@ +/* + * Description: This is intended as a helper script for fb only. + * + * Synopsis: ./fb-upload + * + * Author: Florian "Bluewind" Pritz + * + * Licensed under GPLv3 + * (see COPYING for full license text) + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FORMAT_ARRAY_SIZE 5 + +/* struct which holds the persistent data for progress_callback */ +struct progressData { + struct timeval starttime; + struct timeval last; + double ullast; + int lastStringLength; +}; + +/* load the contents of file fn into data */ +int load_file(const char *fn, char **data, size_t *data_size) +{ + FILE *fp; + size_t buf_size = 1024*1024; /* use 1MiB chunks */ + int size = 0; + + fp = fopen(fn, "rb"); + if (fp == NULL) { + perror("load_file"); + return 1; + } + + /* read the file in buf_size chunks and appened the data to *data */ + while (!feof(fp)) { + *data = realloc(*data, *data_size + buf_size); + if (*data == NULL) { + perror("load_file"); + return 1; + } + size = fread(*data + *data_size, sizeof(char), buf_size, fp); + *data_size += size; + } + + fclose(fp); + + return 0; +} + +void format_bytes(double bytes, char *buf) +{ + double base = 0; + int suffix_pos = 0; + char suffix[FORMAT_ARRAY_SIZE][4] = {"B", "KiB", "MiB", "GiB", "TiB"}; + + base = log(bytes) / log(1024); + suffix_pos = (int)floor(base); + + if (suffix_pos >= FORMAT_ARRAY_SIZE) + suffix_pos = FORMAT_ARRAY_SIZE-1; + + if (suffix_pos > 0) { + snprintf(buf, 64, "%.2f%s", pow(1024, base - suffix_pos), suffix[suffix_pos]); + } else { + snprintf(buf, 64, "%.2fB", bytes); + } +} + +int progress_callback(void *cb_data, + double dltotal, double dlnow, + double ultotal, double ulnow) +{ + struct timeval now; + struct progressData *data = (struct progressData *)cb_data; + double timeSpent = 0; + int printed = 0; + char speed[64]; + char total[64]; + + if (0 == ulnow) + return 0; + + /* upload complete; clean up */ + if (ulnow >= ultotal) { + fprintf(stderr, "%*s\r", data->lastStringLength + 1, ""); + return 0; + } + + gettimeofday(&now, NULL); + + /* only refresh once a second */ + if (data->last.tv_sec == now.tv_sec) + return 0; + + /* calculate time between this and the last call in seconds */ + timeSpent = + (double)(now.tv_sec - data->last.tv_sec) + + (double)(now.tv_usec - data->last.tv_usec) / 1000000.0; + + format_bytes((ulnow - data->ullast) / timeSpent, (char *)&speed); + format_bytes(ulnow, (char *)&total); + + /* print the progress */ + printed = fprintf(stderr, + "\r%s/s uploaded: %.1f%% = %s", + speed, /* upload speed */ + ulnow * 100.0 / ultotal, /* percent uploaded */ + total); /* total data uploaded */ + + /* pad the string if the last one was longer to remove left over characters */ + if (data->lastStringLength > printed) + fprintf(stderr, "%*s", data->lastStringLength - printed, ""); + + /* save current values for the next run */ + data->ullast = ulnow; + data->last = now; + data->lastStringLength = printed; + + return 0; +} + +int main(int argc, char *argv[]) +{ + CURL *curl; + CURLcode res; + + char *userAgent = "fb-client/@VERSION@"; + + struct progressData cb_data = { + .starttime = {.tv_sec = 0, .tv_usec = 0}, + .last = {.tv_sec = 0, .tv_usec = 0}, + .ullast = 0.0, + .lastStringLength = 0 + }; + struct stat statbuf; + + struct curl_httppost *formpost=NULL; + struct curl_httppost *lastptr=NULL; + struct curl_slist *headerlist=NULL; + static const char buf[] = "Expect:"; + struct curl_forms forms[4]; + + char *mode = NULL; + char *data = NULL; + char *url = NULL; + char *file = NULL; + size_t data_size = 0; + + int ret = 0; + + if(argc == 0) + return 1; + + mode = argv[1]; + + if (strncmp(mode, "u", 1) == 0) + file = argv[3]; + + url = argv[2]; + + if (curl_global_init(CURL_GLOBAL_ALL) != 0) { + fprintf(stderr, "Error initializing curl"); + return 10; + } + + if (file) { + if(stat(file, &statbuf) == -1) { + perror("fb-upload"); + return 1; + } + + /* load files with 0 size (/proc files for example) into memory so we can + * determine their real length */ + if (statbuf.st_size == 0) { + if (load_file(file, &data, &data_size) != 0) { + return 1; + } + forms[0].option = CURLFORM_BUFFER; + forms[0].value = basename(file); + forms[1].option = CURLFORM_BUFFERPTR; + forms[1].value = data; + forms[2].option = CURLFORM_BUFFERLENGTH; + forms[2].value = (char *)data_size; + forms[3].option = CURLFORM_END; + } else { + forms[0].option = CURLFORM_FILE; + forms[0].value = file; + forms[1].option = CURLFORM_END; + } + + /* Fill in the file upload field */ + curl_formadd(&formpost, + &lastptr, + CURLFORM_COPYNAME, "file", + CURLFORM_ARRAY, forms, + CURLFORM_END); + } + + curl = curl_easy_init(); + /* initialize custom header list (stating that Expect: 100-continue is not + wanted */ + headerlist = curl_slist_append(headerlist, buf); + if(curl) { + /* what URL that receives this POST */ + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); + curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); + if (file) { + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &cb_data); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback); + } + curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent); + if (formpost) + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); + curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, (long)1); + curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, (long)30); + gettimeofday(&cb_data.starttime, NULL); + res = curl_easy_perform(curl); + + if (res != 0) { + fprintf(stderr, "\n%s\n", curl_easy_strerror(res)); + ret = 1; + } + + /* cleanup */ + curl_easy_cleanup(curl); + if (formpost) + curl_formfree(formpost); + curl_slist_free_all (headerlist); + curl_global_cleanup(); + free(data); + } else { + fprintf(stderr, "Error initializing curl"); + ret = 1; + } + return ret; +} diff --git a/fb-upload.c.in b/fb-upload.c.in deleted file mode 100644 index b0a44ee..0000000 --- a/fb-upload.c.in +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Description: This is intended as a helper script for fb only. - * - * Synopsis: ./fb-upload - * - * Author: Florian "Bluewind" Pritz - * - * Licensed under GPLv3 - * (see COPYING for full license text) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define FORMAT_ARRAY_SIZE 5 - -/* struct which holds the persistent data for progress_callback */ -struct progressData { - struct timeval starttime; - struct timeval last; - double ullast; - int lastStringLength; -}; - -/* load the contents of file fn into data */ -int load_file(const char *fn, char **data, size_t *data_size) -{ - FILE *fp; - size_t buf_size = 1024*1024; /* use 1MiB chunks */ - int size = 0; - - fp = fopen(fn, "rb"); - if (fp == NULL) { - perror("load_file"); - return 1; - } - - /* read the file in buf_size chunks and appened the data to *data */ - while (!feof(fp)) { - *data = realloc(*data, *data_size + buf_size); - if (*data == NULL) { - perror("load_file"); - return 1; - } - size = fread(*data + *data_size, sizeof(char), buf_size, fp); - *data_size += size; - } - - fclose(fp); - - return 0; -} - -void format_bytes(double bytes, char *buf) -{ - double base = 0; - int suffix_pos = 0; - char suffix[FORMAT_ARRAY_SIZE][4] = {"B", "KiB", "MiB", "GiB", "TiB"}; - - base = log(bytes) / log(1024); - suffix_pos = (int)floor(base); - - if (suffix_pos >= FORMAT_ARRAY_SIZE) - suffix_pos = FORMAT_ARRAY_SIZE-1; - - if (suffix_pos > 0) { - snprintf(buf, 64, "%.2f%s", pow(1024, base - suffix_pos), suffix[suffix_pos]); - } else { - snprintf(buf, 64, "%.2fB", bytes); - } -} - -int progress_callback(void *cb_data, - double dltotal, double dlnow, - double ultotal, double ulnow) -{ - struct timeval now; - struct progressData *data = (struct progressData *)cb_data; - double timeSpent = 0; - int printed = 0; - char speed[64]; - char total[64]; - - if (0 == ulnow) - return 0; - - /* upload complete; clean up */ - if (ulnow >= ultotal) { - fprintf(stderr, "%*s\r", data->lastStringLength + 1, ""); - return 0; - } - - gettimeofday(&now, NULL); - - /* only refresh once a second */ - if (data->last.tv_sec == now.tv_sec) - return 0; - - /* calculate time between this and the last call in seconds */ - timeSpent = - (double)(now.tv_sec - data->last.tv_sec) + - (double)(now.tv_usec - data->last.tv_usec) / 1000000.0; - - format_bytes((ulnow - data->ullast) / timeSpent, (char *)&speed); - format_bytes(ulnow, (char *)&total); - - /* print the progress */ - printed = fprintf(stderr, - "\r%s/s uploaded: %.1f%% = %s", - speed, /* upload speed */ - ulnow * 100.0 / ultotal, /* percent uploaded */ - total); /* total data uploaded */ - - /* pad the string if the last one was longer to remove left over characters */ - if (data->lastStringLength > printed) - fprintf(stderr, "%*s", data->lastStringLength - printed, ""); - - /* save current values for the next run */ - data->ullast = ulnow; - data->last = now; - data->lastStringLength = printed; - - return 0; -} - -int main(int argc, char *argv[]) -{ - CURL *curl; - CURLcode res; - - char *userAgent = "fb-client/@VERSION@"; - - struct progressData cb_data = { - .starttime = {.tv_sec = 0, .tv_usec = 0}, - .last = {.tv_sec = 0, .tv_usec = 0}, - .ullast = 0.0, - .lastStringLength = 0 - }; - struct stat statbuf; - - struct curl_httppost *formpost=NULL; - struct curl_httppost *lastptr=NULL; - struct curl_slist *headerlist=NULL; - static const char buf[] = "Expect:"; - struct curl_forms forms[4]; - - char *data = NULL; - size_t data_size = 0; - - int ret = 0; - - /* simple arg check */ - if(argc != 3) - return 1; - - if (curl_global_init(CURL_GLOBAL_ALL) != 0) { - fprintf(stderr, "Error initializing curl"); - return 10; - } - - if(stat(argv[2], &statbuf) == -1) { - perror("fb-upload"); - return 1; - } - - /* load files with 0 size (/proc files for example) into memory so we can - * determine their real length */ - if (statbuf.st_size == 0) { - if (load_file(argv[2], &data, &data_size) != 0) { - return 1; - } - forms[0].option = CURLFORM_BUFFER; - forms[0].value = basename(argv[2]); - forms[1].option = CURLFORM_BUFFERPTR; - forms[1].value = data; - forms[2].option = CURLFORM_BUFFERLENGTH; - forms[2].value = (char *)data_size; - forms[3].option = CURLFORM_END; - } else { - forms[0].option = CURLFORM_FILE; - forms[0].value = argv[2]; - forms[1].option = CURLFORM_END; - } - - /* Fill in the file upload field */ - curl_formadd(&formpost, - &lastptr, - CURLFORM_COPYNAME, "file", - CURLFORM_ARRAY, forms, - CURLFORM_END); - - curl = curl_easy_init(); - /* initialize custom header list (stating that Expect: 100-continue is not - wanted */ - headerlist = curl_slist_append(headerlist, buf); - if(curl) { - /* what URL that receives this POST */ - curl_easy_setopt(curl, CURLOPT_URL, argv[1]); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &cb_data); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback); - curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent); - curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); - curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, (long)1); - curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, (long)30); - gettimeofday(&cb_data.starttime, NULL); - res = curl_easy_perform(curl); - - if (res != 0) { - fprintf(stderr, "\n%s\n", curl_easy_strerror(res)); - ret = 1; - } - - /* cleanup */ - curl_easy_cleanup(curl); - curl_formfree(formpost); - curl_slist_free_all (headerlist); - curl_global_cleanup(); - free(data); - } else { - fprintf(stderr, "Error initializing curl"); - ret = 1; - } - return ret; -} diff --git a/fb.in b/fb.in index 2867230..2327bb6 100644 --- a/fb.in +++ b/fb.in @@ -7,8 +7,7 @@ # (see COPYING for full license text) # #---------------------------------------------------- -# Dependencies: curl -# Optional: xclip +# Optional dependency: xclip #---------------------------------------------------- VERSION="@VERSION@" @@ -56,7 +55,7 @@ do_upload() { TMPFILE=`mktemp "$TMPDIR/data.XXXXXX"` if [ `stat -c %s -- "$file"` -gt "$WARNSIZE" ]; then - WARNSIZE=`curl -s "$PASTEBIN/file/get_max_size"` + WARNSIZE=`$LIBDIR/fb-helper d "$PASTEBIN/file/get_max_size"` if [ `stat -c %s -- "$file"` -gt "$WARNSIZE" ]; then echo "Warning: Your upload is too big and would be rejected. Maximum size is: $WARNSIZE bytes. Skipping..." >&2 EXITCODE=1 @@ -64,26 +63,9 @@ do_upload() { fi fi - # fb-upload handles corner cases (comma in the filename) better - if [ -x "$LIBDIR/fb-upload" ]; then - if ! $LIBDIR/fb-upload "$PASTEBIN/file/do_upload" "$file" > $TMPFILE; then - EXITCODE=1 - return 1 - fi - else - CURLOPTS="-# -n -L -A $USERAGENT $EXTRA" - if [ `stat -c %s -- "$file"` -eq "0" ] || echo "$file" | grep -F -q ","; then - basefilename=`echo "$basefilename" | tr -d ,` - if ! curl $CURLOPTS -F "file=@-;filename=$basefilename" "$PASTEBIN/file/do_upload" < "$file" > $TMPFILE; then - EXITCODE=1 - return 1 - fi - else - if ! curl $CURLOPTS -F "file=@$file" "$PASTEBIN/file/do_upload" > $TMPFILE; then - EXITCODE=1 - return 1 - fi - fi + if ! $LIBDIR/fb-helper u "$PASTEBIN/file/do_upload" "$file" > $TMPFILE; then + EXITCODE=1 + return 1 fi sed '$d' $TMPFILE >&2 URL=`tail -1 $TMPFILE`"$EXTENSION" @@ -162,9 +144,9 @@ if [ "$DELETE" ] || [ "$GET" ]; then for i in "$@"; do i=$(id_from_arg "$i") if [ "$DELETE" ]; then - curl -n -L -A $USERAGENT "$PASTEBIN/file/delete/$i" || EXITCODE=1 + $LIBDIR/fb-helper d "$PASTEBIN/file/delete/$i" || EXITCODE=1 elif [ "$GET" ]; then - curl -s -o - -A $USERAGENT "$PASTEBIN/$i" || EXITCODE=1 + $LIBDIR/fb-helper d "$PASTEBIN/$i" || EXITCODE=1 fi done elif [ $# -eq 0 ]; then @@ -184,7 +166,7 @@ else for i in "$@"; do if echo "$i" | grep -qE "^(f|ht)tp(s)?://.+"; then cd $TMPDIR - if ! curl -# -A $USERAGENT -O "$i"; then + if ! $LIBDIR/fb-helper d "$i" > "`basename "$i"`"; then EXITCODE=1 continue fi -- cgit v1.2.3-24-g4f1b