| #include <stdlib.h> | |
| #include <string.h> | |
| #include <stdio.h> | |
| #include <sys/stat.h> | |
| #include "upnpreplyparse.h" | |
| #include "minixml.h" | |
| static void | |
| NameValueParserStartElt(void * d, const char * name, int l) | |
| { | |
| struct NameValueParserData * data = (struct NameValueParserData *)d; | |
| if(l>63) | |
| l = 63; | |
| memcpy(data->curelt, name, l); | |
| data->curelt[l] = '\0'; | |
| } | |
| static void | |
| NameValueParserGetData(void * d, const char * datas, int l) | |
| { | |
| struct NameValueParserData * data = (struct NameValueParserData *)d; | |
| struct NameValue * nv; | |
| nv = malloc(sizeof(struct NameValue)); | |
| memset(nv, 0, sizeof(struct NameValue)); | |
| nv->value = (char *) malloc(l+1); | |
| memset(nv->value, 0, l+1); | |
| strncpy(nv->name, data->curelt, 64); | |
| memcpy(nv->value, datas, l); | |
| LIST_INSERT_HEAD( &(data->head), nv, entries); | |
| } | |
| void ParseNameValue(const char * buffer, int bufsize, | |
| struct NameValueParserData * data) | |
| { | |
| struct xmlparser parser; | |
| LIST_INIT(&(data->head)); | |
| /* init xmlparser object */ | |
| parser.xmlstart = buffer; | |
| parser.xmlsize = bufsize; | |
| parser.data = data; | |
| parser.starteltfunc = NameValueParserStartElt; | |
| parser.endeltfunc = 0; | |
| parser.datafunc = NameValueParserGetData; | |
| parser.attfunc = 0; | |
| parsexml(&parser); | |
| } | |
| void ClearNameValueList(struct NameValueParserData * pdata) | |
| { | |
| struct NameValue * nv; | |
| while((nv = pdata->head.lh_first) != NULL) | |
| { | |
| if (nv->value) | |
| free(nv->value); | |
| LIST_REMOVE(nv, entries); | |
| free(nv); | |
| } | |
| } | |
| char * | |
| GetValueFromNameValueList(struct NameValueParserData * pdata, | |
| const char * Name) | |
| { | |
| struct NameValue * nv; | |
| char * p = NULL; | |
| for(nv = pdata->head.lh_first; | |
| (nv != NULL) && (p == NULL); | |
| nv = nv->entries.le_next) | |
| { | |
| if(strcmp(nv->name, Name) == 0) | |
| p = nv->value; | |
| } | |
| return p; | |
| } | |
| char * | |
| GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, | |
| const char * Name) | |
| { | |
| struct NameValue * nv; | |
| char * p = NULL; | |
| char * pname; | |
| for(nv = pdata->head.lh_first; | |
| (nv != NULL) && (p == NULL); | |
| nv = nv->entries.le_next) | |
| { | |
| pname = strrchr(nv->name, ':'); | |
| if(pname) | |
| pname++; | |
| else | |
| pname = nv->name; | |
| if(strcmp(pname, Name)==0) | |
| p = nv->value; | |
| } | |
| return p; | |
| } | |
| /* debug all-in-one function | |
| * do parsing then display to stdout */ | |
| void DisplayNameValueList(char * buffer, int bufsize) | |
| { | |
| struct NameValueParserData pdata; | |
| struct NameValue * nv; | |
| ParseNameValue(buffer, bufsize, &pdata); | |
| for(nv = pdata.head.lh_first; | |
| nv != NULL; | |
| nv = nv->entries.le_next) | |
| { | |
| printf("%s = %s\n", nv->name, nv->value); | |
| } | |
| ClearNameValueList(&pdata); | |
| } | |
| /* MUST free the returned buffer after this call */ | |
| char *mini_UPnPGetFirstElement(char *file_start, unsigned int len, char *tag_name, unsigned int tag_name_len) | |
| { | |
| char * line; | |
| unsigned long file_end; | |
| unsigned long string_begin=0; | |
| unsigned long string_end=0; | |
| char *tag_name_first=NULL; | |
| char *tag_name_second=NULL; | |
| char *buf=NULL; | |
| unsigned int string_len=0; | |
| if (file_start == NULL || tag_name == NULL) | |
| return NULL; | |
| if (len <= 0 || tag_name_len <= 0) | |
| return NULL; | |
| tag_name_first = (char *)malloc(tag_name_len+3); | |
| if (tag_name_first == NULL) | |
| return NULL; | |
| memcpy(tag_name_first+1, tag_name, tag_name_len); | |
| tag_name_first[0] = '<'; | |
| tag_name_first[tag_name_len+1] = '>'; | |
| tag_name_first[tag_name_len+2] = 0; | |
| tag_name_second = (char *)malloc(tag_name_len+4); | |
| if (tag_name_second == NULL) { | |
| free(tag_name_first); | |
| return NULL; | |
| } | |
| memcpy(tag_name_second+2, tag_name, tag_name_len); | |
| tag_name_second[0] = '<'; | |
| tag_name_second[1] = '/'; | |
| tag_name_second[tag_name_len+2] = '>'; | |
| tag_name_second[tag_name_len+3] = 0; | |
| line = file_start; | |
| file_end = (unsigned long)file_start + len; | |
| while ((unsigned long)line < (file_end-tag_name_len-3)) | |
| { | |
| if (strncasecmp(line, tag_name_first, tag_name_len+2) == 0) { | |
| if (string_begin == 0) { | |
| string_begin = (unsigned long)line + tag_name_len + 2; | |
| } | |
| else { | |
| //DEBUG_ERR("Duplicated tag %s\n", tag_name_first); | |
| free(tag_name_first); | |
| free(tag_name_second); | |
| return NULL; | |
| } | |
| } | |
| else if (strncasecmp(line, tag_name_second, tag_name_len+3) == 0) { | |
| if (string_begin == 0) { | |
| //DEBUG_ERR("Missing tag %s\n", tag_name_first); | |
| free(tag_name_first); | |
| free(tag_name_second); | |
| return NULL; | |
| } | |
| else { | |
| string_end = (unsigned long)line; | |
| break; | |
| } | |
| } | |
| line++; | |
| } | |
| free(tag_name_first); | |
| free(tag_name_second); | |
| if (string_begin < string_end) { | |
| string_len = string_end - string_begin; | |
| buf = (char *)malloc(string_len+1); | |
| if (buf == NULL) | |
| return NULL; | |
| memcpy(buf, (char *)string_begin, string_len); | |
| buf[string_len] = 0; | |
| return buf; | |
| } | |
| else { | |
| //DEBUG_ERR("XML parse erroe!\n"); | |
| return NULL; | |
| } | |
| } | |
| char *mini_UPnPGetFirstElementAndReturnAddr(char *file_start, unsigned int len, char *tag_name, unsigned int tag_name_len, char *buf) | |
| { | |
| char * line; | |
| unsigned long file_end; | |
| unsigned long string_begin=0; | |
| unsigned long string_end=0; | |
| char *tag_name_first=NULL; | |
| char *tag_name_second=NULL; | |
| unsigned int string_len=0; | |
| char *end=NULL; | |
| unsigned char found=0; | |
| if (file_start == NULL || tag_name == NULL || buf == NULL) | |
| return NULL; | |
| if (len <= 0 || tag_name_len <= 0) | |
| return NULL; | |
| tag_name_first = (char *)malloc(tag_name_len+3); | |
| if (tag_name_first == NULL) | |
| return NULL; | |
| memcpy(tag_name_first+1, tag_name, tag_name_len); | |
| tag_name_first[0] = '<'; | |
| tag_name_first[tag_name_len+1] = '>'; | |
| tag_name_first[tag_name_len+2] = 0; | |
| tag_name_second = (char *)malloc(tag_name_len+4); | |
| if (tag_name_second == NULL) { | |
| free(tag_name_first); | |
| return NULL; | |
| } | |
| memcpy(tag_name_second+2, tag_name, tag_name_len); | |
| tag_name_second[0] = '<'; | |
| tag_name_second[1] = '/'; | |
| tag_name_second[tag_name_len+2] = '>'; | |
| tag_name_second[tag_name_len+3] = 0; | |
| line = file_start; | |
| file_end = (unsigned long)file_start + len; | |
| while ((unsigned long)line < (file_end-tag_name_len-3)) | |
| { | |
| if (strncasecmp(line, tag_name_first, tag_name_len+2) == 0) { | |
| if (string_begin == 0) { | |
| string_begin = (unsigned long)line + tag_name_len + 2; | |
| } | |
| else { | |
| //DEBUG_ERR("Duplicated tag %s\n", tag_name_first); | |
| free(tag_name_first); | |
| free(tag_name_second); | |
| return NULL; | |
| } | |
| } | |
| else if (strncasecmp(line, tag_name_second, tag_name_len+3) == 0) { | |
| if (string_begin == 0) { | |
| //DEBUG_ERR("Missing tag %s\n", tag_name_first); | |
| free(tag_name_first); | |
| free(tag_name_second); | |
| return NULL; | |
| } | |
| else { | |
| string_end = (unsigned long)line; | |
| end = (char *)(line + (tag_name_len+3)); | |
| found = 1; | |
| break; | |
| } | |
| } | |
| line++; | |
| } | |
| free(tag_name_first); | |
| free(tag_name_second); | |
| if (string_begin < string_end) { | |
| string_len = string_end - string_begin; | |
| memcpy(buf, (char *)string_begin, string_len); | |
| buf[string_len] = 0; | |
| return end; | |
| } | |
| else { | |
| if (found) { | |
| buf[0] = 0; | |
| return end; | |
| } | |
| else | |
| return NULL; | |
| } | |
| } | |
| char *mini_UPnP_UploadXML(char *file_path) | |
| { | |
| FILE *fp = NULL; | |
| int retVal = 0; | |
| struct stat file_info; | |
| char *buf=NULL; | |
| unsigned int fileLen=0; | |
| unsigned int num_read=0; | |
| char *membuf=NULL; | |
| buf = file_path; | |
| retVal = stat(buf, &file_info ); | |
| if ( retVal == -1 ) { | |
| //printf("Failed to get file info. EXITING\n"); | |
| return NULL; | |
| } | |
| fileLen = file_info.st_size; | |
| if ( ( fp = fopen( buf, "rb" ) ) == NULL ) { | |
| printf("Failed to open file [%s]. EXITING\n", buf); | |
| return NULL; | |
| } | |
| if ( ( membuf = ( char * )malloc( fileLen + 1 ) ) == NULL ) { | |
| fclose( fp ); | |
| printf("mini_UPnP_UploadXML Out of memory! EXITING\n"); | |
| return NULL; | |
| } | |
| num_read = fread( membuf, 1, fileLen, fp ); | |
| if ( num_read != fileLen ) { | |
| fclose( fp ); | |
| free( membuf ); | |
| printf("mini_UPnP_UploadXML File length mismatched! EXITING\n"); | |
| return NULL; | |
| } | |
| membuf[fileLen] = 0; | |
| fclose( fp ); | |
| return membuf; | |
| } | |
| char *get_token(char *data, char *token) | |
| { | |
| char *ptr=data; | |
| int len=0, idx=0; | |
| while (*ptr && *ptr != '\n' ) { | |
| if (*ptr == '=') { | |
| if (len <= 1) | |
| return NULL; | |
| memcpy(token, data, len); | |
| /* delete ending space */ | |
| for (idx=len-1; idx>=0; idx--) { | |
| if (token[idx] != ' ') | |
| break; | |
| } | |
| token[idx+1] = '\0'; | |
| return ptr+1; | |
| } | |
| len++; | |
| ptr++; | |
| } | |
| return NULL; | |
| } | |
| int get_value(char *data, char *value) | |
| { | |
| char *ptr=data; | |
| int len=0, idx, i; | |
| while (*ptr && *ptr != '\n' && *ptr != '\r') { | |
| len++; | |
| ptr++; | |
| } | |
| /* delete leading space */ | |
| idx = 0; | |
| while (len-idx > 0) { | |
| if (data[idx] != ' ') | |
| break; | |
| idx++; | |
| } | |
| len -= idx; | |
| /* delete bracing '"' */ | |
| if (data[idx] == '"') { | |
| for (i=idx+len-1; i>idx; i--) { | |
| if (data[i] == '"') { | |
| idx++; | |
| len = i - idx; | |
| } | |
| break; | |
| } | |
| } | |
| if (len > 0) { | |
| memcpy(value, &data[idx], len); | |
| value[len] = '\0'; | |
| } | |
| return len; | |
| } | |