From 2dd0ef8fe2953cbdec20f4dcd016c93f12117fad Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sun, 16 Sep 2018 21:54:19 -0400 Subject: [PATCH] /ctdl/u/username/userpic is now complete --- webcit-ng/ctdlclient.c | 22 ++++++++++- webcit-ng/room_functions.c | 17 ++++---- webcit-ng/user_functions.c | 79 ++++++++++++++++++++++---------------- webcit-ng/webcit.h | 1 + 4 files changed, 74 insertions(+), 45 deletions(-) diff --git a/webcit-ng/ctdlclient.c b/webcit-ng/ctdlclient.c index 0a5e1fbcd..2467b1237 100644 --- a/webcit-ng/ctdlclient.c +++ b/webcit-ng/ctdlclient.c @@ -18,9 +18,29 @@ struct ctdlsession *cpool = NULL; // linked list of connections to the Citade pthread_mutex_t cpool_mutex = PTHREAD_MUTEX_INITIALIZER; // Lock it before modifying +/* + * Read a specific number of bytes of binary data from the Citadel server. + * Returns the number of bytes read or -1 for error. + */ +int ctdl_read_binary(struct ctdlsession *ctdl, char *buf, int bytes_requested) +{ + int bytes_read = 0; + int c = 0; + + while (bytes_read < bytes_requested) { + c = read(ctdl->sock, &buf[bytes_read], bytes_requested-bytes_read); + if (c <= 0) { + syslog(LOG_DEBUG, "Socket error or zero-length read"); + return (-1); + } + bytes_read += c; + } + return (bytes_read); +} + + /* * Read a newline-terminated line of text from the Citadel server. - * Implemented in terms of client_read() and is therefore transparent... * Returns the string length or -1 for error. */ int ctdl_readline(struct ctdlsession *ctdl, char *buf, int maxbytes) diff --git a/webcit-ng/room_functions.c b/webcit-ng/room_functions.c index 403e83f70..75ef7bcf5 100644 --- a/webcit-ng/room_functions.c +++ b/webcit-ng/room_functions.c @@ -28,7 +28,7 @@ long *get_msglist(struct ctdlsession *c, char *which_msgs) ctdl_printf(c, "MSGS %s", which_msgs); ctdl_readline(c, buf, sizeof(buf)); - if (buf[0] == '1') + if (buf[0] == '1') { do { if (num_msgs >= num_alloc) { if (num_alloc == 0) { @@ -42,6 +42,7 @@ long *get_msglist(struct ctdlsession *c, char *which_msgs) ctdl_readline(c, buf, sizeof(buf)); msglist[num_msgs++] = atol(buf); } while (strcmp(buf, "000")); // this makes the last element a "0" terminator + } return msglist; } @@ -57,8 +58,7 @@ int match_etags(char *taglist, long msgnum) int i = 0; char tag[1024]; - if (msgnum <= 0) // no msgnum? no match. - { + if (msgnum <= 0) { // no msgnum? no match. return (0); } @@ -67,24 +67,21 @@ int match_etags(char *taglist, long msgnum) striplt(tag); char *lq = (strchr(tag, '"')); char *rq = (strrchr(tag, '"')); - if (lq < rq) // has two double quotes - { + if (lq < rq) { // has two double quotes strcpy(rq, ""); strcpy(tag, ++lq); } striplt(tag); - if (!strcmp(tag, "*")) // wildcard match - { + if (!strcmp(tag, "*")) { // wildcard match return (1); } long tagmsgnum = atol(tag); - if ((tagmsgnum > 0) && (tagmsgnum == msgnum)) // match - { + if ((tagmsgnum > 0) && (tagmsgnum == msgnum)) { // match return (1); } } - return (0); // no match + return (0); // no match } diff --git a/webcit-ng/user_functions.c b/webcit-ng/user_functions.c index b3d360f00..10e81211f 100644 --- a/webcit-ng/user_functions.c +++ b/webcit-ng/user_functions.c @@ -18,25 +18,44 @@ /* * Fetch a user photo (avatar) */ -void fetch_user_photo(struct http_transaction *h, struct ctdlsession *c) +void fetch_user_photo(struct http_transaction *h, struct ctdlsession *c, char *username) { - char username[1024]; + char buf[1024]; + int content_length = 0; + char content_type[1024]; + char *image = NULL; + int actual_length = 0; + + ctdl_printf(c, "DLUI %s", username); + ctdl_readline(c, buf, sizeof(buf)); + if (buf[0] == '6') { + content_length = extract_int(&buf[4], 0); + extract_token(content_type, &buf[4], 3, '|', sizeof content_type); + + image = malloc(content_length); + if (image == NULL) { + do_502(h); + return; + } + actual_length = ctdl_read_binary(c, image, content_length); - extract_token(username, h->uri, 3, '/', sizeof username); + add_response_header(h, strdup("Content-type"), strdup(content_type)); + h->response_code = 200; + h->response_string = strdup("OK"); + h->response_body_length = actual_length; + h->response_body = image; + return; + } - do_404(h); // FIXME finish this + do_404(h); } /* * Fetch a user bio (profile) */ -void fetch_user_bio(struct http_transaction *h, struct ctdlsession *c) +void fetch_user_bio(struct http_transaction *h, struct ctdlsession *c, char *username) { - char username[1024]; - - extract_token(username, h->uri, 3, '/', sizeof username); - do_404(h); // FIXME finish this } @@ -44,21 +63,19 @@ void fetch_user_bio(struct http_transaction *h, struct ctdlsession *c) /* * Client requested an object related to a user. */ -void object_in_user(struct http_transaction *h, struct ctdlsession *c) +void object_in_user(struct http_transaction *h, struct ctdlsession *c, char *requested_username) { - char buf[1024]; - long msgnum = (-1); - char unescaped_euid[1024]; + char object_name[1024]; - extract_token(buf, h->uri, 4, '/', sizeof buf); + extract_token(object_name, h->uri, 4, '/', sizeof object_name); - if (!strcasecmp(buf, "userpic")) { // user photo (avatar) - fetch_user_photo(h, c); + if (!strcasecmp(object_name, "userpic")) { // user photo (avatar) + fetch_user_photo(h, c, requested_username); return; } - if (!strcasecmp(buf, "bio")) { // user bio (profile) - fetch_user_bio(h, c); + if (!strcasecmp(object_name, "bio")) { // user bio (profile) + fetch_user_bio(h, c, requested_username); return; } @@ -71,7 +88,7 @@ void object_in_user(struct http_transaction *h, struct ctdlsession *c) * Handle REST/DAV requests for the user itself (such as /ctdl/u/username * or /ctdl/i/username/ but *not* specific properties of the user) */ -void the_user_itself(struct http_transaction *h, struct ctdlsession *c) +void the_user_itself(struct http_transaction *h, struct ctdlsession *c, char *username) { do_404(h); } @@ -98,40 +115,34 @@ void ctdl_u(struct http_transaction *h, struct ctdlsession *c) extract_token(requested_username, h->uri, 3, '/', sizeof requested_username); unescape_input(requested_username); - if (IsEmptyStr(requested_username)) { // /ctdl/u/ + if (IsEmptyStr(requested_username)) { // /ctdl/u/ user_list(h, c); return; } - // Try to access the user... - if (strcasecmp(requested_username, c->room)) { - do_404(h); - } else { - do_404(h); - return; - } + // At this point we have extracted the name of the user we're interested in. + // FIXME should we validate it? - // At this point we have accessed the requested user account. - if (num_tokens(h->uri, '/') == 4) { // /ctdl/u/username - the_user_itself(h, c); + if (num_tokens(h->uri, '/') == 4) { // /ctdl/u/username + the_user_itself(h, c, requested_username); return; } extract_token(buf, h->uri, 4, '/', sizeof buf); if (num_tokens(h->uri, '/') == 5) { if (IsEmptyStr(buf)) { - the_user_itself(h, c); // /ctdl/u/username/ ( same as /ctdl/u/username ) + the_user_itself(h, c, requested_username); // /ctdl/u/username/ ( same as /ctdl/u/username ) } else { - object_in_user(h, c); // /ctdl/u/username/object + object_in_user(h, c, requested_username); // /ctdl/u/username/object } return; } if (num_tokens(h->uri, '/') == 6) { - object_in_user(h, c); // /ctdl/u/username/object/ or possibly /ctdl/u/username/object/component + object_in_user(h, c, requested_username); // /ctdl/u/username/object/ or possibly /ctdl/u/username/object/component return; } - // If we get to this point, the client specified a valid user but requested an action we don't know how to perform. + // If we get to this point, the client requested an action we don't know how to perform. do_404(h); } diff --git a/webcit-ng/webcit.h b/webcit-ng/webcit.h index af08f6fdd..36f47acf7 100644 --- a/webcit-ng/webcit.h +++ b/webcit-ng/webcit.h @@ -157,6 +157,7 @@ void download_mime_component(struct http_transaction *h, struct ctdlsession *c, StrBuf *text2html(const char *supplied_charset, int treat_as_wiki, char *roomname, long msgnum, StrBuf *Source); StrBuf *variformat2html(StrBuf *Source); int ctdl_readline(struct ctdlsession *ctdl, char *buf, int maxbytes); +int ctdl_read_binary(struct ctdlsession *ctdl, char *buf, int bytes_requested); void ctdl_c(struct http_transaction *h, struct ctdlsession *c); int webserver(char *webserver_interface, int webserver_port, int webserver_protocol); void ctdl_printf(struct ctdlsession *ctdl, const char *format,...); -- 2.30.2