Subversion Repositories RepoView

Rev

Rev 41 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

/* $Id: multipart.c 42 2024-08-22 05:25:09Z nishi $ */

#include "rv_multipart.h"

#include "rv_util.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct multipart_entry** multipart_entries = NULL;

void rv_free_multipart(void) {
        if(multipart_entries == NULL) return;
        int i;
        for(i = 0; multipart_entries[i] != NULL; i++) {
                free(multipart_entries[i]->name);
                free(multipart_entries[i]->data);
                free(multipart_entries[i]);
        }
        free(multipart_entries);
}

struct multipart_entry* rv_get_multipart(const char* name) {
        if(multipart_entries == NULL) return NULL;
        int i;
        for(i = 0; multipart_entries[i] != NULL; i++) {
                if(strcmp(multipart_entries[i]->name, name) == 0) {
                        return multipart_entries[i];
                }
        }
        return NULL;
}

void rv_parse_multipart(unsigned char* buffer, char* boundary, unsigned long long length) {
        unsigned long long i;
        int incr = 0;
        int phase = 0;
        unsigned long long fstart = 0;
        char* b = rv_strcat3("--", boundary, "\r");
        char* eb = rv_strcat3("--", boundary, "--\r");
        multipart_entries = malloc(sizeof(*multipart_entries));
        multipart_entries[0] = NULL;
        char* name = NULL;
        for(i = 0;; i++) {
                if(i == length || buffer[i] == '\n') {
                        char* line = malloc(i - incr + 1);
                        memcpy(line, buffer + incr, i - incr);
                        line[i - incr] = 0;
                        if(line[0] == '\r' && phase == 0) {
                                phase = 1;
                                fstart = i + 1;
                        } else if(strcmp(b, line) == 0 || strcmp(eb, line) == 0) {
                                if(phase == 1) {
                                        unsigned long long fend = i - strlen(line) - 2;
                                        char* data = buffer + fstart;
                                        unsigned long long datalen = fend - fstart;
                                        struct multipart_entry* entry = malloc(sizeof(*entry));
                                        entry->length = datalen;
                                        entry->data = malloc(datalen);
                                        entry->name = rv_strdup(name);
                                        unsigned long long j;
                                        for(j = 0; j < datalen; j++) entry->data[j] = data[j];

                                        struct multipart_entry** old_entries = multipart_entries;
                                        for(j = 0; old_entries[j] != NULL; j++)
                                                ;
                                        multipart_entries = malloc(sizeof(*multipart_entries) * (j + 2));
                                        for(j = 0; old_entries[j] != NULL; j++) {
                                                multipart_entries[j] = old_entries[j];
                                        }
                                        multipart_entries[j] = entry;
                                        multipart_entries[j + 1] = NULL;
                                        free(old_entries);
                                }
                                phase = 0;
                                if(strcmp(eb, line) == 0) {
                                        free(line);
                                        break;
                                }
                        } else if(phase == 0) {
                                line[strlen(line) - 1] = 0;
                                int j;
                                for(j = 0; line[j] != 0; j++) {
                                        if(line[j] == ':') {
                                                line[j] = 0;
                                                char* value = "";
                                                j++;
                                                for(; line[j] != 0; j++) {
                                                        if(line[j] != ' ' && line[j] != '\t') {
                                                                value = line + j;
                                                                break;
                                                        }
                                                }
                                                if(strcasecmp(line, "Content-Disposition") == 0) {
                                                        int j;
                                                        int incrval = 0;
                                                        for(j = 0;; j++) {
                                                                if(value[j] == ';' || value[j] == 0) {
                                                                        char oldc = value[j];
                                                                        value[j] = 0;
                                                                        char* kv = value + incrval;
                                                                        j++;
                                                                        for(; value[j] != 0; j++) {
                                                                                if(value[j] != ' ' && value[j] != '\t') break;
                                                                        }
                                                                        incrval = j;
                                                                        int k;
                                                                        for(k = 0; kv[k] != 0; k++) {
                                                                                if(kv[k] == '=') {
                                                                                        kv[k] = 0;
                                                                                        if(strcmp(kv, "name") == 0) {
                                                                                                if(name != NULL) free(name);
                                                                                                name = malloc(strlen(kv + k + 1) + 1);
                                                                                                char* nkv = kv + k + 1;
                                                                                                int l = 0;
                                                                                                int incrn = 0;
                                                                                                for(l = 0; nkv[l] != 0; l++) {
                                                                                                        if(nkv[l] != '"') {
                                                                                                                name[incrn++] = nkv[l];
                                                                                                        }
                                                                                                }
                                                                                                name[incrn] = 0;
                                                                                        }
                                                                                        break;
                                                                                }
                                                                        }
                                                                        if(oldc == 0) break;
                                                                }
                                                        }
                                                }
                                                break;
                                        }
                                }
                        }
                        free(line);
                        incr = i + 1;
                        if(i == length) break;
                }
        }
        if(name != NULL) free(name);
        free(b);
}