Newer
Older
do {
next=form->next; /* the following form line */
free(form->line); /* free the line */
free(form); /* free the struct */
} while((form=next)); /* continue */
}
/* external function to free up a whole form post chain */
void curl_formfree(struct HttpPost *form)
{
struct HttpPost *next;
if(!form)
/* no form to free, just get out of this */
return;
do {
next=form->next; /* the following form line */
/* recurse to sub-contents */
if(form->more)
curl_formfree(form->more);
if( !(form->flags & HTTPPOST_PTRNAME) && form->name)
if( !(form->flags & HTTPPOST_PTRCONTENTS) && form->contents)
free(form->contents); /* free the contents */
if(form->contenttype)
free(form->contenttype); /* free the content type */
free(form); /* free the struct */
} while((form=next)); /* continue */
struct FormData *Curl_getFormData(struct HttpPost *post,
int *sizep)
{
struct FormData *form = NULL;
struct FormData *firstform;
struct HttpPost *file;
int size =0;
char *boundary;
char *fileboundary=NULL;
struct curl_slist* curList;
if(!post)
return NULL; /* no input => no output! */
boundary = Curl_FormBoundary();
/* Make the first line of the output */
AddFormDataf(&form,
"Content-Type: multipart/form-data;"
" boundary=%s\r\n",
boundary);
/* we DO NOT count that line since that'll be part of the header! */
firstform = form;
do {
/* boundary */
size += AddFormDataf(&form, "--%s\r\n", boundary);
size += AddFormData(&form,
"Content-Disposition: form-data; name=\"", 0);
size += AddFormData(&form, post->name, post->namelength);
size += AddFormData(&form, "\"", 0);
if(post->more) {
/* If used, this is a link to more file names, we must then do
the magic to include several files with the same field name */
fileboundary = Curl_FormBoundary();
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
size += AddFormDataf(&form,
"\r\nContent-Type: multipart/mixed,"
" boundary=%s\r\n",
fileboundary);
}
file = post;
do {
if(post->more) {
/* if multiple-file */
size += AddFormDataf(&form,
"\r\n--%s\r\nContent-Disposition: attachment; filename=\"%s\"",
fileboundary, file->contents);
}
else if(post->flags & HTTPPOST_FILENAME) {
size += AddFormDataf(&form,
"; filename=\"%s\"",
post->contents);
}
if(file->contenttype) {
/* we have a specified type */
size += AddFormDataf(&form,
"\r\nContent-Type: %s",
file->contenttype);
}
curList = file->contentheader;
while( curList ) {
/* Process the additional headers specified for this form */
size += AddFormDataf( &form, "\r\n%s", curList->data );
curList = curList->next;
}
#if 0
/* The header Content-Transfer-Encoding: seems to confuse some receivers
* (like the built-in PHP engine). While I can't see any reason why it
* should, I can just as well skip this to the benefit of the users who
* are using such confused receivers.
*/
if(file->contenttype &&
!strnequal("text/", file->contenttype, 5)) {
/* this is not a text content, mention our binary encoding */
size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
size += AddFormData(&form, "\r\n\r\n", 0);
if((post->flags & HTTPPOST_FILENAME) ||
(post->flags & HTTPPOST_READFILE)) {
/* we should include the contents from the specified file */
FILE *fileread;
char buffer[1024];
int nread;
fileread = strequal("-", file->contents)?stdin:
/* binary read for win32 crap */
/*VMS??*/ fopen(file->contents, "rb"); /* ONLY ALLOWS FOR STREAM FILES ON VMS */
/*VMS?? Stream files are OK, as are FIXED & VAR files WITHOUT implied CC */
/*VMS?? For implied CC, every record needs to have a \n appended & 1 added to SIZE */
if(fileread) {
while((nread = fread(buffer, 1, 1024, fileread))) {
size += AddFormData(&form,
buffer,
nread);
}
if(fileread != stdin)
fclose(fileread);
}
Daniel Stenberg
committed
else {
/* File wasn't found, add a nothing field! */
size += AddFormData(&form, "", 0);
}
}
else {
size += AddFormData(&form, post->contents, post->contentslength);
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
}
} while((file = file->more)); /* for each specified file for this field */
if(post->more) {
/* this was a multiple-file inclusion, make a termination file
boundary: */
size += AddFormDataf(&form,
"\r\n--%s--",
fileboundary);
free(fileboundary);
}
} while((post=post->next)); /* for each field */
/* end-boundary for everything */
size += AddFormDataf(&form,
"\r\n--%s--\r\n",
boundary);
*sizep = size;
free(boundary);
return firstform;
}
int Curl_FormInit(struct Form *form, struct FormData *formdata )
form->data = formdata;
form->sent = 0;
return 0;
}
/* fread() emulation */
int Curl_FormReader(char *buffer,
size_t size,
size_t nitems,
FILE *mydata)
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
{
struct Form *form;
int wantedsize;
int gotsize = 0;
form=(struct Form *)mydata;
wantedsize = size * nitems;
if(!form->data)
return -1; /* nothing, error, empty */
do {
if( (form->data->length - form->sent ) > wantedsize - gotsize) {
memcpy(buffer + gotsize , form->data->line + form->sent,
wantedsize - gotsize);
form->sent += wantedsize-gotsize;
return wantedsize;
}
memcpy(buffer+gotsize,
form->data->line + form->sent,
(form->data->length - form->sent) );
gotsize += form->data->length - form->sent;
form->sent = 0;
form->data = form->data->next; /* advance */
} while(form->data);
/* If we got an empty line and we have more data, we proceed to the next
line immediately to avoid returning zero before we've reached the end.
This is the bug reported November 22 1999 on curl 6.3. (Daniel) */
return gotsize;
}
/* possible (old) fread() emulation that copies at most one line */
int Curl_FormReadOneLine(char *buffer,
size_t size,
size_t nitems,
FILE *mydata)
{
struct Form *form;
int wantedsize;
int gotsize;
form=(struct Form *)mydata;
wantedsize = size * nitems;
if(!form->data)
return -1; /* nothing, error, empty */
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
do {
if( (form->data->length - form->sent ) > wantedsize ) {
memcpy(buffer, form->data->line + form->sent, wantedsize);
form->sent += wantedsize;
return wantedsize;
}
memcpy(buffer,
form->data->line + form->sent,
gotsize = (form->data->length - form->sent) );
form->sent = 0;
form->data = form->data->next; /* advance */
} while(!gotsize && form->data);
/* If we got an empty line and we have more data, we proceed to the next
line immediately to avoid returning zero before we've reached the end.
This is the bug reported November 22 1999 on curl 6.3. (Daniel) */
return gotsize;
}
#ifdef _FORM_DEBUG
int FormAddTest(const char * errormsg,
struct HttpPost **httppost,
struct HttpPost **last_post,
...)
{
int result;
va_list arg;
va_start(arg, last_post);
if ((result = FormAdd(httppost, last_post, arg)))
fprintf (stderr, "ERROR doing FormAdd ret: %d action: %s\n", result,
errormsg);
va_end(arg);
return result;
}
int main()
{
char name1[] = "simple_COPYCONTENTS";
char name2[] = "COPYCONTENTS_+_CONTENTTYPE";
char name3[] = "PTRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH";
char name4[] = "simple_PTRCONTENTS";
char name5[] = "PTRCONTENTS_+_CONTENTSLENGTH";
char name6[] = "PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE";
char name7[] = "FILE1_+_CONTENTTYPE";
char name8[] = "FILE1_+_FILE2";
char name9[] = "FILE1_+_FILE2_+_FILE3";
char name10[] = "ARRAY: FILE1_+_FILE2_+_FILE3";
char name11[] = "FILECONTENT";
char value1[] = "value for simple COPYCONTENTS";
char value2[] = "value for COPYCONTENTS + CONTENTTYPE";
char value3[] = "value for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH";
char value4[] = "value for simple PTRCONTENTS";
char value5[] = "value for PTRCONTENTS + CONTENTSLENGTH";
char value6[] = "value for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE";
char value7[] = "inet_ntoa_r.h";
char value8[] = "Makefile.b32.resp";
char type2[] = "image/gif";
char type6[] = "text/plain";
char type7[] = "text/html";
int name3length = strlen(name3);
int value3length = strlen(value3);
int value5length = strlen(value4);
int value6length = strlen(value5);
int errors = 0;
int size;
int nread;
char buffer[4096];
struct HttpPost *httppost=NULL;
struct HttpPost *last_post=NULL;
struct FormData *form;
struct Form formread;
if (FormAddTest("simple COPYCONTENTS test", &httppost, &last_post,
CURLFORM_COPYNAME, name1, CURLFORM_COPYCONTENTS, value1,
CURLFORM_END))
++errors;
if (FormAddTest("COPYCONTENTS + CONTENTTYPE test", &httppost, &last_post,
CURLFORM_COPYNAME, name2, CURLFORM_COPYCONTENTS, value2,
CURLFORM_CONTENTTYPE, type2, CURLFORM_END))
++errors;
/* make null character at start to check that contentslength works
correctly */
name3[1] = '\0';
value3[1] = '\0';
if (FormAddTest("PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH test",
&httppost, &last_post,
CURLFORM_PTRNAME, name3, CURLFORM_COPYCONTENTS, value3,
CURLFORM_CONTENTSLENGTH, value3length,
CURLFORM_NAMELENGTH, name3length, CURLFORM_END))
++errors;
if (FormAddTest("simple PTRCONTENTS test", &httppost, &last_post,
CURLFORM_COPYNAME, name4, CURLFORM_PTRCONTENTS, value4,
CURLFORM_END))
++errors;
/* make null character at start to check that contentslength works
correctly */
value5[1] = '\0';
if (FormAddTest("PTRCONTENTS + CONTENTSLENGTH test", &httppost, &last_post,
CURLFORM_COPYNAME, name5, CURLFORM_PTRCONTENTS, value5,
CURLFORM_CONTENTSLENGTH, value5length, CURLFORM_END))
++errors;
/* make null character at start to check that contentslength works
correctly */
value6[1] = '\0';
if (FormAddTest("PTRCONTENTS + CONTENTSLENGTH + CONTENTTYPE test",
&httppost, &last_post,
CURLFORM_COPYNAME, name6, CURLFORM_PTRCONTENTS, value6,
CURLFORM_CONTENTSLENGTH, value6length,
CURLFORM_CONTENTTYPE, type6, CURLFORM_END))
++errors;
if (FormAddTest("FILE + CONTENTTYPE test", &httppost, &last_post,
CURLFORM_COPYNAME, name7, CURLFORM_FILE, value7,
CURLFORM_CONTENTTYPE, type7, CURLFORM_END))
++errors;
if (FormAddTest("FILE1 + FILE2 test", &httppost, &last_post,
CURLFORM_COPYNAME, name8, CURLFORM_FILE, value7,
CURLFORM_FILE, value8, CURLFORM_END))
++errors;
if (FormAddTest("FILE1 + FILE2 + FILE3 test", &httppost, &last_post,
CURLFORM_COPYNAME, name9, CURLFORM_FILE, value7,
CURLFORM_FILE, value8, CURLFORM_FILE, value7, CURLFORM_END))
forms[0].option = CURLFORM_FILE;
forms[0].value = value7;
forms[1].option = CURLFORM_FILE;
forms[1].value = value8;
forms[2].option = CURLFORM_FILE;
forms[2].value = value7;
forms[3].option = CURLFORM_END;
if (FormAddTest("FILE1 + FILE2 + FILE3 ARRAY test", &httppost, &last_post,
CURLFORM_COPYNAME, name10, CURLFORM_ARRAY, forms,
CURLFORM_END))
++errors;
if (FormAddTest("FILECONTENT test", &httppost, &last_post,
CURLFORM_COPYNAME, name11, CURLFORM_FILECONTENT, value7,
CURLFORM_END))
++errors;
form=Curl_getFormData(httppost, &size);
Curl_FormInit(&formread, form);
do {
nread = Curl_FormReader(buffer, 1, sizeof(buffer),
(FILE *)&formread);
if(-1 == nread)
break;
fwrite(buffer, nread, 1, stdout);
} while(1);
fprintf(stdout, "size: %d\n", size);
if (errors)
fprintf(stdout, "\n==> %d Test(s) failed!\n", errors);
else
fprintf(stdout, "\nAll Tests seem to have worked (please check output)\n");
return 0;
}
#endif
#ifdef _OLD_FORM_DEBUG
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
int main(int argc, char **argv)
{
#if 0
char *testargs[]={
"name1 = data in number one",
"name2 = number two data",
"test = @upload"
};
#endif
int i;
char *nextarg;
struct HttpPost *httppost=NULL;
struct HttpPost *last_post=NULL;
struct HttpPost *post;
int size;
int nread;
char buffer[4096];
struct FormData *form;
struct Form formread;
for(i=1; i<argc; i++) {
if( FormParse( argv[i],
&httppost,
&last_post)) {
fprintf(stderr, "Illegally formatted input field: '%s'!\n",
argv[i]);
return 1;
}
}
form=Curl_getFormData(httppost, &size);
Curl_FormInit(&formread, form);
do {
nread = Curl_FormReader(buffer, 1, sizeof(buffer),
(FILE *)&formread);
if(-1 == nread)
break;
} while(1);
fprintf(stderr, "size: %d\n", size);
return 0;
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78