#include "setup.h"
#include <curl/curl.h>
#include "rawstr.h"
#define ENABLE_CURLX_PRINTF
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_mfiles.h"
#include "tool_msgs.h"
#include "tool_formparse.h"
#include "memdebug.h"
int formparse(struct Configurable *config,
const char *input,
struct curl_httppost **httppost,
struct curl_httppost **last_post,
bool literal_value)
{
char name[256];
char *contents = NULL;
char major[128];
char minor[128];
char *contp;
const char *type = NULL;
char *sep;
char *sep2;
if((1 == sscanf(input, "%255[^=]=", name)) &&
((contp = strchr(input, '=')) != NULL)) {
contents = strdup(contp+1);
if(!contents) {
fprintf(config->errors, "out of memory\n");
return 1;
}
contp = contents;
if('@' == contp[0] && !literal_value) {
struct multi_files *multi_start = NULL;
struct multi_files *multi_current = NULL;
contp++;
do {
char *ptr;
char *filename = NULL;
sep = strchr(contp, ';');
sep2 = strchr(contp, ',');
if(sep2 && (sep2 < sep)) {
sep = sep2;
}
type = NULL;
if(sep) {
bool semicolon = (';' == *sep) ? TRUE : FALSE;
*sep = '\0';
ptr = sep+1;
while(semicolon && ptr && (','!= *ptr)) {
while(ISSPACE(*ptr))
ptr++;
if(checkprefix("type=", ptr)) {
type = &ptr[5];
if(2 != sscanf(type, "%127[^/]/%127[^;,\n]",
major, minor)) {
warnf(config, "Illegally formatted content-type field!\n");
Curl_safefree(contents);
FreeMultiInfo(&multi_start, &multi_current);
return 2;
}
sep = (char *)type + strlen(major)+strlen(minor)+1;
if(*sep==';') {
if(!checkprefix(";filename=", sep)) {
sep2 = strchr(sep+1, ';');
if(sep2)
sep = sep2;
else
sep = sep + strlen(sep);
}
}
else
semicolon = FALSE;
if(*sep) {
*sep = '\0';
ptr = sep+1;
}
else
ptr = NULL;
}
else if(checkprefix("filename=", ptr)) {
filename = &ptr[9];
ptr = strchr(filename, ';');
if(!ptr) {
ptr = strchr(filename, ',');
}
if(ptr) {
*ptr = '\0';
ptr++;
}
}
else
break;
}
sep = ptr;
}
if(!AddMultiFiles(contp, type, filename, &multi_start,
&multi_current)) {
warnf(config, "Error building form post!\n");
Curl_safefree(contents);
FreeMultiInfo(&multi_start, &multi_current);
return 3;
}
contp = sep;
} while(sep && *sep);
if(multi_start) {
struct curl_forms *forms = NULL;
struct multi_files *ptr = multi_start;
unsigned int i, count = 0;
while(ptr) {
ptr = ptr->next;
++count;
}
forms = malloc((count+1)*sizeof(struct curl_forms));
if(!forms) {
fprintf(config->errors, "Error building form post!\n");
Curl_safefree(contents);
FreeMultiInfo(&multi_start, &multi_current);
return 4;
}
for(i = 0, ptr = multi_start; i < count; ++i, ptr = ptr->next) {
forms[i].option = ptr->form.option;
forms[i].value = ptr->form.value;
}
forms[count].option = CURLFORM_END;
FreeMultiInfo(&multi_start, &multi_current);
if(curl_formadd(httppost, last_post,
CURLFORM_COPYNAME, name,
CURLFORM_ARRAY, forms, CURLFORM_END) != 0) {
warnf(config, "curl_formadd failed!\n");
Curl_safefree(forms);
Curl_safefree(contents);
return 5;
}
Curl_safefree(forms);
}
}
else {
struct curl_forms info[4];
int i = 0;
char *ct = literal_value ? NULL : strstr(contp, ";type=");
info[i].option = CURLFORM_COPYNAME;
info[i].value = name;
i++;
if(ct) {
info[i].option = CURLFORM_CONTENTTYPE;
info[i].value = &ct[6];
i++;
ct[0] = '\0';
}
if(contp[0]=='<' && !literal_value) {
info[i].option = CURLFORM_FILECONTENT;
info[i].value = contp+1;
i++;
info[i].option = CURLFORM_END;
if(curl_formadd(httppost, last_post,
CURLFORM_ARRAY, info, CURLFORM_END ) != 0) {
warnf(config, "curl_formadd failed, possibly the file %s is bad!\n",
contp+1);
Curl_safefree(contents);
return 6;
}
}
else {
#ifdef CURL_DOES_CONVERSIONS
if(convert_to_network(contp, strlen(contp))) {
warnf(config, "curl_formadd failed!\n");
Curl_safefree(contents);
return 7;
}
#endif
info[i].option = CURLFORM_COPYCONTENTS;
info[i].value = contp;
i++;
info[i].option = CURLFORM_END;
if(curl_formadd(httppost, last_post,
CURLFORM_ARRAY, info, CURLFORM_END) != 0) {
warnf(config, "curl_formadd failed!\n");
Curl_safefree(contents);
return 8;
}
}
}
}
else {
warnf(config, "Illegally formatted input field!\n");
return 1;
}
Curl_safefree(contents);
return 0;
}