MINIUPNP_LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalPacketsReceived(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; char * buffer; int bufsize; unsigned int r = 0; char * p; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived"); r = my_atoui(p); ClearNameValueList(&pdata); return r; }
MINIUPNP_LIBSPEC int UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID) { /*struct NameValueParserData pdata;*/ struct UPNParg * DeletePinholeArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!uniqueID) return UPNPCOMMAND_INVALID_ARGS; DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); if(DeletePinholeArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; DeletePinholeArgs[0].elt = "UniqueID"; DeletePinholeArgs[0].val = uniqueID; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "DeletePinhole", DeletePinholeArgs, &bufsize); free(DeletePinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; }
/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. * if the third arg is not null the value is copied to it. * at least 16 bytes must be available * * Return values : * 0 : SUCCESS * NON ZERO : ERROR Either an UPnP error code or an unknown error. * * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. */ LIBSPEC int UPNP_GetExternalIPAddress(const char * controlURL, const char * servicetype, char * extIpAdd) { struct NameValueParserData pdata; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!extIpAdd || !controlURL || !servicetype) return UPNPCOMMAND_INVALID_ARGS; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/ p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress"); if(p) { strncpy(extIpAdd, p, 16 ); extIpAdd[15] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else extIpAdd[0] = '\0'; p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; }
LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost) { /*struct NameValueParserData pdata;*/ struct UPNParg * DeletePortMappingArgs; char buffer[4096]; int bufsize = 4096; struct NameValueParserData pdata; const char * resVal; int ret; if(!extPort || !proto) return UPNPCOMMAND_INVALID_ARGS; DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg)); DeletePortMappingArgs[0].elt = "NewRemoteHost"; DeletePortMappingArgs[0].val = remoteHost; DeletePortMappingArgs[1].elt = "NewExternalPort"; DeletePortMappingArgs[1].val = extPort; DeletePortMappingArgs[2].elt = "NewProtocol"; DeletePortMappingArgs[2].val = proto; simpleUPnPcommand(-1, controlURL, servicetype, "DeletePortMapping", DeletePortMappingArgs, buffer, &bufsize); /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); free(DeletePortMappingArgs); return ret; }
/* UPNP_GetStatusInfo() call the corresponding UPNP method * returns the current status and uptime */ void UPNP_GetStatusInfo(const char * controlURL, const char * servicetype, char * status, unsigned int * uptime) { struct NameValueParserData pdata; char buffer[4096]; int bufsize = 4096; char * p; char* up; if(!status && !uptime) return; simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize); ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ up = GetValueFromNameValueList(&pdata, "NewUptime"); p = GetValueFromNameValueList(&pdata, "NewConnectionStatus"); if(status) { if(p){ strncpy(status, p, 64 ); status[63] = '\0'; }else status[0]= '\0'; } if(uptime){ if(p) sscanf(up,"%u",uptime); else uptime = 0; } ClearNameValueList(&pdata); }
LIBSPEC int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries) { struct NameValueParserData pdata; char * buffer; int bufsize; char* p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } #ifdef DEBUG DisplayNameValueList(buffer, bufsize); #endif ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); if(numEntries && p) { *numEntries = 0; sscanf(p, "%u", numEntries); ret = UPNPCOMMAND_SUCCESS; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; }
/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method * returns the connection type */ LIBSPEC int UPNP_GetConnectionTypeInfo(const char * controlURL, const char * servicetype, char * connectionType) { struct NameValueParserData pdata; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!connectionType) return UPNPCOMMAND_INVALID_ARGS; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetConnectionTypeInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewConnectionType"); /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/ /* PossibleConnectionTypes will have several values.... */ if(p) { strncpy(connectionType, p, 64 ); connectionType[63] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else connectionType[0] = '\0'; p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; }
//--------------------------------------------------------------------------- AnsiString TRsyncConfigAdapter::GetParamValue(AnsiString moduleName, AnsiString paramName){ TModuleHolder* aHolder = GetModuleHolder(moduleName); if(aHolder == NULL){ return "Invalid module name"; } TStringList* params = aHolder->nvp; for(int i = 0; i < params->Count; i++){ AnsiString oneLine = params->Strings[i]; AnsiString sName, sValue; if(ParseNameValue(oneLine, sName, sValue)){ if(sName == paramName){ return sValue; } } } return ""; }
MINIUPNP_LIBSPEC int UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * inPort, const char * inClient, const char * desc, const char * proto, const char * remoteHost, const char * leaseDuration, char * reservedPort) { struct UPNParg * AddPortMappingArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!inPort || !inClient || !proto || !extPort) return UPNPCOMMAND_INVALID_ARGS; AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); if(AddPortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; AddPortMappingArgs[0].elt = "NewRemoteHost"; AddPortMappingArgs[0].val = remoteHost; AddPortMappingArgs[1].elt = "NewExternalPort"; AddPortMappingArgs[1].val = extPort; AddPortMappingArgs[2].elt = "NewProtocol"; AddPortMappingArgs[2].val = proto; AddPortMappingArgs[3].elt = "NewInternalPort"; AddPortMappingArgs[3].val = inPort; AddPortMappingArgs[4].elt = "NewInternalClient"; AddPortMappingArgs[4].val = inClient; AddPortMappingArgs[5].elt = "NewEnabled"; AddPortMappingArgs[5].val = "1"; AddPortMappingArgs[6].elt = "NewPortMappingDescription"; AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; AddPortMappingArgs[7].elt = "NewLeaseDuration"; AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "AddAnyPortMapping", AddPortMappingArgs, &bufsize); free(AddPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { char *p; p = GetValueFromNameValueList(&pdata, "NewReservedPort"); if(p) { strncpy(reservedPort, p, 6); reservedPort[5] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else { ret = UPNPCOMMAND_INVALID_RESPONSE; } } ClearNameValueList(&pdata); return ret; }
/* UPNP_GetStatusInfo() call the corresponding UPNP method * returns the current status and uptime */ MINIUPNP_LIBSPEC int UPNP_GetStatusInfo(const char * controlURL, const char * servicetype, char * status, unsigned int * uptime, char * lastconnerror) { struct NameValueParserData pdata; char * buffer; int bufsize; char * p; char * up; char * err; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!status && !uptime) return UPNPCOMMAND_INVALID_ARGS; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ free(buffer); buffer = NULL; up = GetValueFromNameValueList(&pdata, "NewUptime"); p = GetValueFromNameValueList(&pdata, "NewConnectionStatus"); err = GetValueFromNameValueList(&pdata, "NewLastConnectionError"); if(p && up) ret = UPNPCOMMAND_SUCCESS; if(status) { if(p){ strncpy(status, p, 64 ); status[63] = '\0'; }else status[0]= '\0'; } if(uptime) { if(up) sscanf(up,"%u",uptime); else *uptime = 0; } if(lastconnerror) { if(err) { strncpy(lastconnerror, err, 64 ); lastconnerror[63] = '\0'; } else lastconnerror[0] = '\0'; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; }
int parse_form_encoded(llist* entries) { long content_length; node* window; char *boundary; int bytesread = 0; int numentries = 0; if (CONTENT_LENGTH != NULL) content_length = atol(CONTENT_LENGTH); else return 0; if (content_length < 0) { return 0; } if (content_length > MAX_CONTENT_LENGTH) { return 0; } if (CONTENT_TYPE == NULL) { return 0; } boundary = strstr(CONTENT_TYPE, "boundary="); if (boundary == NULL) { boundary = getenv("Qzone-Param-Boundary"); if (NULL == boundary) { return 0; } } else { boundary += (sizeof(char) * 9); } /* create list */ list_create(entries); window = entries->head; buffer_file = (char*)malloc(content_length*sizeof(char)); if(NULL == buffer_file) { return 0; } int n = 0; //while ((n=fread(buffer_file+bytesread, sizeof(char),content_length-bytesread,stdin) )> 0) while ((n=read(fileno(stdin), buffer_file+bytesread, content_length-bytesread) )> 0) { bytesread += n; } if (bytesread != content_length) { return 0; } int boundlen = strlen(boundary)+2; char step[boundlen+1]; step[0] = '-'; step[1] = '-'; memcpy(step+2, boundary, boundlen-2); step[boundlen] = '\0'; int pos = MYBF(buffer_file, content_length, step, boundlen); if (-1 == pos) { return 0; } int oldpos = pos+boundlen+2; char *head_end = "\r\n\r\n"; int head_end_len = strlen(head_end); int head_end_pos = 0; while(1) { int isNewFormat = 0; //新的格式,在传文件的时候加上自定义参数length numentries++; head_end_pos = MYBF(buffer_file+oldpos, content_length-oldpos, head_end, head_end_len); if (head_end_pos> 0) { char *tmp = buffer_file+oldpos; char temp = tmp[head_end_pos]; tmp[head_end_pos] = '\0'; if ((strstr(tmp, "filename=") != NULL) && (strstr(tmp, "name=") != NULL)) { //int fd = open("/tmp/cgihtml.log", O_RDWR|O_APPEND, 0777); char *slen = strstr(tmp, "filelength=\""); int len = 0; if (NULL != slen) { /* if (-1 != fd) { char tt[1024]; snprintf(tt, 1024, "boundary file length=%s\n", slen); write(fd, tt, strlen(tt)); } */ len = atoi(slen+strlen("filelength=\"")); } else { /* if (-1 != fd) { char tt[1024]; snprintf(tt, 1024, "boundary file length=%s\n", "NULL"); write(fd, tt, strlen(tt)); } */ slen = getenv("filelength"); if (NULL != slen) { /* if (-1 != fd) { char tt[1024]; snprintf(tt, 1024, "env file length=%s\n", slen); write(fd, tt, strlen(tt)); } */ len = atoi(slen); } else { /* if (-1 != fd) { char tt[1024]; snprintf(tt, 1024, "env file length=%s\n", "NULL"); write(fd, tt, strlen(tt)); } */ } } if (len > 0 && len < content_length-oldpos-head_end_pos-head_end_len-boundlen-2) { if (0 == memcmp(tmp+head_end_pos+head_end_len+len+2, step, boundlen)) { isNewFormat = 1; pos = head_end_pos+head_end_len+len+2; /* if (-1 != fd) { char tt[1024]; snprintf(tt, 1024, "new file format%s\n", "NULL"); write(fd, tt, strlen(tt)); } */ } } //close(fd); } tmp[head_end_pos] = temp; } if (0 == isNewFormat) { pos = MYBF(buffer_file+oldpos, content_length-oldpos, step, boundlen); if(-1 == pos) { int randlen = 2+boundlen+6; //const TCHAR c_szFormCompletionFormat[] = _T("\r\n--%s--\r\n\r\n"); if(oldpos+randlen< content_length)//兼容控件225最后一个为unicode分隔符 { char *tmp = buffer_file + content_length - randlen; if (tmp[0] != '\r' || tmp[1] != 0 || tmp[2] != '\n' || tmp[3] != 0 || tmp[4] != '-' || tmp[5] != 0 || tmp[6] != '-' || tmp[7] != 0) { break; } else { pos = content_length-randlen-oldpos+2; buffer_file[oldpos+pos-2]='\r'; buffer_file[oldpos+pos-1]='\n'; buffer_file[oldpos+pos+boundlen]='-'; buffer_file[oldpos+pos+boundlen+1]='-'; } } else { break; } } } ParseNameValue(buffer_file+oldpos, pos, entries, &window); if (buffer_file[oldpos+pos+boundlen]=='-'&&buffer_file[oldpos+pos+boundlen+1]=='-') { break; } else if (buffer_file[oldpos+pos+boundlen]!='\r'||buffer_file[oldpos+pos+boundlen+1]!='\n') { break; } oldpos += pos+boundlen+2; } return numentries; }
int UPNP_GetGenericPortMappingEntry(const char * controlURL, const char * servicetype, const char * index, char * extPort, char * intClient, char * intPort, char * protocol, char * desc, char * enabled, char * rHost, char * duration) { struct NameValueParserData pdata; struct UPNParg * GetPortMappingArgs; char buffer[4096]; int bufsize = 4096; char * p; int r = -1; intClient[0] = '\0'; intPort[0] = '\0'; GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); GetPortMappingArgs[0].elt = "NewPortMappingIndex"; GetPortMappingArgs[0].val = index; simpleUPnPcommand(-1, controlURL, servicetype, "GetGenericPortMappingEntry", GetPortMappingArgs, buffer, &bufsize); ParseNameValue(buffer, bufsize, &pdata); p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); if(p && rHost) { strncpy(rHost, p, 64); rHost[63] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewExternalPort"); if(p && extPort) { strncpy(extPort, p, 6); extPort[5] = '\0'; r = 0; } p = GetValueFromNameValueList(&pdata, "NewProtocol"); if(p && protocol) { strncpy(protocol, p, 4); protocol[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewInternalClient"); if(p && intClient) { strncpy(intClient, p, 16); intClient[15] = '\0'; r = 0; } p = GetValueFromNameValueList(&pdata, "NewInternalPort"); if(p && intPort) { strncpy(intPort, p, 6); intPort[5] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewEnabled"); if(p && enabled) { strncpy(enabled, p, 4); enabled[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); if(p && desc) { strncpy(desc, p, 80); desc[79] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); if(p && duration) { strncpy(duration, p, 16); duration[15] = '\0'; } ClearNameValueList(&pdata); free(GetPortMappingArgs); return r; }
int image_get_jpeg_date_xmp(const char * path, char ** date) { FILE *img; unsigned char buf[8]; char *data = NULL, *newdata; uint16_t offset; struct NameValueParserData xml; char * exif; int ret = 1; size_t nread; img = fopen(path, "r"); if( !img ) return(-1); nread = fread(&buf, 2, 1, img); if( (nread < 1) || (buf[0] != 0xFF) || (buf[1] != 0xD8) ) { fclose(img); return(-1); } memset(&buf, 0, sizeof(buf)); while( !feof(img) ) { while( nread > 0 && buf[0] != 0xFF && !feof(img) ) nread = fread(&buf, 1, 1, img); while( nread > 0 && buf[0] == 0xFF && !feof(img) ) nread = fread(&buf, 1, 1, img); if( feof(img) ) break; if( buf[0] == 0xE1 ) // APP1 marker { offset = 0; nread = fread(&buf, 2, 1, img); if( nread < 1 ) break; memcpy(&offset, buf, 2); offset = SWAP16(offset) - 2; if( offset < 30 ) { fseek(img, offset, SEEK_CUR); continue; } newdata = realloc(data, 30); if( !newdata ) break; data = newdata; nread = fread(data, 29, 1, img); if( nread < 1 ) break; offset -= 29; if( strcmp(data, "http://ns.adobe.com/xap/1.0/") != 0 ) { fseek(img, offset, SEEK_CUR); continue; } newdata = realloc(data, offset+1); if( !newdata ) break; data = newdata; nread = fread(data, offset, 1, img); if( nread < 1 ) break; ParseNameValue(data, offset, &xml, 0); exif = GetValueFromNameValueList(&xml, "DateTimeOriginal"); if( !exif ) { ClearNameValueList(&xml); break; } *date = realloc(*date, strlen(exif)+1); strcpy(*date, exif); ClearNameValueList(&xml); ret = 0; break; } else { offset = 0; nread = fread(&buf, 2, 1, img); if( nread < 1 ) break; memcpy(&offset, buf, 2); offset = SWAP16(offset) - 2; fseek(img, offset, SEEK_CUR); } } fclose(img); free(data); return ret; }
void ParseUPnPClient(char *location) { char buf[8192]; struct sockaddr_in dest; int s, n, do_headers = 0, nread = 0; struct timeval tv; char *addr, *path, *port_str; long port = 80; char *off = NULL, *p; int content_len = sizeof(buf); struct NameValueParserData xml; int client; enum client_types type = 0; uint32_t flags = 0; char *model, *serial, *name; if (strncmp(location, "http://", 7) != 0) return; path = location + 7; port_str = strsep(&path, "/"); if (!path) return; addr = strsep(&port_str, ":"); if (port_str) { port = strtol(port_str, NULL, 10); if (!port) port = 80; } memset(&dest, '\0', sizeof(dest)); if (!inet_aton(addr, &dest.sin_addr)) return; /* Check if the client is already in cache */ dest.sin_family = AF_INET; dest.sin_port = htons(port); s = socket(PF_INET, SOCK_STREAM, 0); if( s < 0 ) return; tv.tv_sec = 0; tv.tv_usec = 500000; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); if( connect(s, (struct sockaddr*)&dest, sizeof(struct sockaddr_in)) < 0 ) goto close; n = snprintf(buf, sizeof(buf), "GET /%s HTTP/1.0\r\n" "HOST: %s:%ld\r\n\r\n", path, addr, port); if( write(s, buf, n) < 1 ) goto close; while( (n = read(s, buf+nread, sizeof(buf)-nread-1)) > 0 ) { nread += n; buf[nread] = '\0'; n = nread; p = buf; while( !off && n-- > 0 ) { if(p[0]=='\r' && p[1]=='\n' && p[2]=='\r' && p[3]=='\n') { off = p + 4; do_headers = 1; } p++; } if( !off ) continue; if( do_headers ) { p = buf; if( strncmp(p, "HTTP/", 5) != 0 ) goto close; while(*p != ' ' && *p != '\t') p++; /* If we don't get a 200 status, ignore it */ if( strtol(p, NULL, 10) != 200 ) goto close; if( (p = strcasestr(p, "Content-Length:")) ) content_len = strtol(p+15, NULL, 10); do_headers = 0; } if( buf + nread - off >= content_len ) break; } close: close(s); if( !off ) return; nread -= off - buf; ParseNameValue(off, nread, &xml); model = GetValueFromNameValueList(&xml, "modelName"); serial = GetValueFromNameValueList(&xml, "serialNumber"); name = GetValueFromNameValueList(&xml, "friendlyName"); if( model ) { DPRINTF(E_DEBUG, L_SSDP, "Model: %s\n", model); if( strstr(model, "Roku SoundBridge") ) { type = ERokuSoundBridge; flags |= FLAG_MS_PFS; flags |= FLAG_AUDIO_ONLY; flags |= FLAG_MIME_WAV_WAV; } else if( strcmp(model, "Samsung DTV DMR") == 0 && serial ) { DPRINTF(E_DEBUG, L_SSDP, "Serial: %s\n", serial); /* The Series B I saw was 20081224DMR. Series A should be older than that. */ if( atoi(serial) > 20081200 ) { type = ESamsungSeriesB; flags |= FLAG_SAMSUNG; flags |= FLAG_DLNA; flags |= FLAG_NO_RESIZE; } } else { if( name && (strcmp(name, "marantz DMP") == 0) ) { type = EMarantzDMP; flags |= FLAG_DLNA; flags |= FLAG_MIME_WAV_WAV; } } } ClearNameValueList(&xml); if( !type ) return; /* Add this client to the cache if it's not there already. */ client = SearchClientCache(dest.sin_addr, 1); if( client < 0 ) { for( client=0; client<CLIENT_CACHE_SLOTS; client++ ) { if( clients[client].addr.s_addr ) continue; get_remote_mac(dest.sin_addr, clients[client].mac); clients[client].addr = dest.sin_addr; DPRINTF(E_DEBUG, L_SSDP, "Added client [%d/%s/%02X:%02X:%02X:%02X:%02X:%02X] to cache slot %d.\n", type, inet_ntoa(clients[client].addr), clients[client].mac[0], clients[client].mac[1], clients[client].mac[2], clients[client].mac[3], clients[client].mac[4], clients[client].mac[5], client); break; } } clients[client].type = type; clients[client].flags = flags; clients[client].age = time(NULL); }
/* UPNP_GetListOfPortMappings() * * Possible UPNP Error codes : * 606 Action not Authorized * 730 PortMappingNotFound - no port mapping is found in the specified range. * 733 InconsistantParameters - NewStartPort and NewEndPort values are not * consistent. */ MINIUPNP_LIBSPEC int UPNP_GetListOfPortMappings(const char * controlURL, const char * servicetype, const char * startPort, const char * endPort, const char * protocol, const char * numberOfPorts, struct PortMappingParserData * data) { struct NameValueParserData pdata; struct UPNParg * GetListOfPortMappingsArgs; const char * p; char * buffer; int bufsize; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!startPort || !endPort || !protocol) return UPNPCOMMAND_INVALID_ARGS; GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); if(GetListOfPortMappingsArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetListOfPortMappingsArgs[0].elt = "NewStartPort"; GetListOfPortMappingsArgs[0].val = startPort; GetListOfPortMappingsArgs[1].elt = "NewEndPort"; GetListOfPortMappingsArgs[1].val = endPort; GetListOfPortMappingsArgs[2].elt = "NewProtocol"; GetListOfPortMappingsArgs[2].val = protocol; GetListOfPortMappingsArgs[3].elt = "NewManage"; GetListOfPortMappingsArgs[3].val = "1"; GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetListOfPortMappings", GetListOfPortMappingsArgs, &bufsize); free(GetListOfPortMappingsArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; /*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/ /*if(p) { printf("NewPortListing : %s\n", p); }*/ /*printf("NewPortListing(%d chars) : %s\n", pdata.portListingLength, pdata.portListing);*/ if(pdata.portListing) { /*struct PortMapping * pm; int i = 0;*/ ParsePortListing(pdata.portListing, pdata.portListingLength, data); ret = UPNPCOMMAND_SUCCESS; /* for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next) { printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n", i, pm->protocol, pm->externalPort, pm->internalClient, pm->internalPort, pm->description, pm->remoteHost); i++; } */ /*FreePortListing(&data);*/ } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); /*printf("%.*s", bufsize, buffer);*/ return ret; }
MINIUPNP_LIBSPEC int UPNP_GetGenericPortMappingEntry(const char * controlURL, const char * servicetype, const char * index, char * extPort, char * intClient, char * intPort, char * protocol, char * desc, char * enabled, char * rHost, char * duration) { struct NameValueParserData pdata; struct UPNParg * GetPortMappingArgs; char * buffer; int bufsize; char * p; int r = UPNPCOMMAND_UNKNOWN_ERROR; if(!index) return UPNPCOMMAND_INVALID_ARGS; intClient[0] = '\0'; intPort[0] = '\0'; GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); if(GetPortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetPortMappingArgs[0].elt = "NewPortMappingIndex"; GetPortMappingArgs[0].val = index; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetGenericPortMappingEntry", GetPortMappingArgs, &bufsize); free(GetPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); if(p && rHost) { strncpy(rHost, p, 64); rHost[63] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewExternalPort"); if(p && extPort) { strncpy(extPort, p, 6); extPort[5] = '\0'; r = UPNPCOMMAND_SUCCESS; } p = GetValueFromNameValueList(&pdata, "NewProtocol"); if(p && protocol) { strncpy(protocol, p, 4); protocol[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewInternalClient"); if(p && intClient) { strncpy(intClient, p, 16); intClient[15] = '\0'; r = 0; } p = GetValueFromNameValueList(&pdata, "NewInternalPort"); if(p && intPort) { strncpy(intPort, p, 6); intPort[5] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewEnabled"); if(p && enabled) { strncpy(enabled, p, 4); enabled[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); if(p && desc) { strncpy(desc, p, 80); desc[79] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); if(p && duration) { strncpy(duration, p, 16); duration[15] = '\0'; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { r = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &r); } ClearNameValueList(&pdata); return r; }
void parse_nfo(const char *path, metadata_t *m) { FILE *nfo; char buf[65536]; struct NameValueParserData xml; struct stat file; size_t nread; char *val, *val2; if( stat(path, &file) != 0 || file.st_size > 65536 ) { DPRINTF(E_INFO, L_METADATA, "Not parsing very large .nfo file %s\n", path); return; } DPRINTF(E_DEBUG, L_METADATA, "Parsing .nfo file: %s\n", path); nfo = fopen(path, "r"); if( !nfo ) return; nread = fread(&buf, 1, sizeof(buf), nfo); ParseNameValue(buf, nread, &xml, 0); //printf("\ttype: %s\n", GetValueFromNameValueList(&xml, "rootElement")); val = GetValueFromNameValueList(&xml, "title"); if( val ) { char *esc_tag = unescape_tag(val, 1); val2 = GetValueFromNameValueList(&xml, "episodetitle"); if( val2 ) { char *esc_tag2 = unescape_tag(val2, 1); xasprintf(&m->title, "%s - %s", esc_tag, esc_tag2); free(esc_tag2); } else { m->title = escape_tag(esc_tag, 1); } free(esc_tag); } val = GetValueFromNameValueList(&xml, "plot"); if( val ) { char *esc_tag = unescape_tag(val, 1); m->comment = escape_tag(esc_tag, 1); free(esc_tag); } val = GetValueFromNameValueList(&xml, "capturedate"); if( val ) { char *esc_tag = unescape_tag(val, 1); m->date = escape_tag(esc_tag, 1); free(esc_tag); } val = GetValueFromNameValueList(&xml, "genre"); if( val ) { free(m->genre); char *esc_tag = unescape_tag(val, 1); m->genre = escape_tag(esc_tag, 1); free(esc_tag); } val = GetValueFromNameValueList(&xml, "mime"); if( val ) { free(m->mime); char *esc_tag = unescape_tag(val, 1); m->mime = escape_tag(esc_tag, 1); free(esc_tag); } ClearNameValueList(&xml); fclose(nfo); }
void ParseUPnPClient(char *location) { char buf[8192]; struct sockaddr_in dest; int s, n, do_headers = 0, nread = 0; struct timeval tv; char *addr, *path, *port_str; long port = 80; char *off = NULL, *p; int content_len = sizeof(buf); struct NameValueParserData xml; int client; int type = 0; char *model, *serial, *name; if (strncmp(location, "http://", 7) != 0) return; path = location + 7; port_str = strsep(&path, "/"); if (!path) return; addr = strsep(&port_str, ":"); if (port_str) { port = strtol(port_str, NULL, 10); if (!port) port = 80; } memset(&dest, '\0', sizeof(dest)); if (!inet_aton(addr, &dest.sin_addr)) return; /* Check if the client is already in cache */ dest.sin_family = AF_INET; dest.sin_port = htons(port); s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) return; tv.tv_sec = 0; tv.tv_usec = 500000; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); if (connect(s, (struct sockaddr*)&dest, sizeof(struct sockaddr_in)) < 0) goto close; n = snprintf(buf, sizeof(buf), "GET /%s HTTP/1.0\r\n" "HOST: %s:%ld\r\n\r\n", path, addr, port); if (write(s, buf, n) < 1) goto close; while ((n = read(s, buf+nread, sizeof(buf)-nread-1)) > 0) { nread += n; buf[nread] = '\0'; n = nread; p = buf; while (!off && (n-- > 0)) { if (p[0] == '\r' && p[1] == '\n' && p[2] == '\r' && p[3] == '\n') { off = p + 4; do_headers = 1; } p++; } if (!off) continue; if (do_headers) { p = buf; if (strncmp(p, "HTTP/", 5) != 0) goto close; while (*p != ' ' && *p != '\t') p++; /* If we don't get a 200 status, ignore it */ if (strtol(p, NULL, 10) != 200) goto close; p = strcasestr(p, "Content-Length:"); if (p) content_len = strtol(p+15, NULL, 10); do_headers = 0; } if ((buf + nread - off) >= content_len) break; } close: close(s); if (!off) return; nread -= off - buf; ParseNameValue(off, nread, &xml, 0); model = GetValueFromNameValueList(&xml, "modelName"); serial = GetValueFromNameValueList(&xml, "serialNumber"); name = GetValueFromNameValueList(&xml, "friendlyName"); if (model) { int i; DPRINTF(E_DEBUG, L_SSDP, "Model: %s\n", model); for (i = 0; client_types[i].name; i++) { if (client_types[i].match_type != EModelName) continue; if (strstr(model, client_types[i].match) != NULL) { type = i; break; } } /* Special Samsung handling. It's very hard to tell Series A from B */ if (type > 0 && client_types[type].type == ESamsungSeriesB) { if (serial) { DPRINTF(E_DEBUG, L_SSDP, "Serial: %s\n", serial); /* The Series B I saw was 20081224DMR. Series A should be older than that. */ if (atoi(serial) < 20081201) type = 0; } else { type = 0; } } if (type == 0 && name != NULL) { for (i = 0; client_types[i].name; i++) { if (client_types[i].match_type != EFriendlyNameSSDP) continue; if (strcmp(name, client_types[i].match) == 0) { type = i; break; } } } } ClearNameValueList(&xml); if (!type) return; /* Add this client to the cache if it's not there already. */ client = SearchClientCache(dest.sin_addr, 1); if (client < 0) { AddClientCache(dest.sin_addr, type); } else { clients[client].type = type; clients[client].age = time(NULL); } }
/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping * the result is returned in the intClient and intPort strings * please provide 16 and 6 bytes of data */ MINIUPNP_LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, const char * remoteHost, char * intClient, char * intPort, char * desc, char * enabled, char * leaseDuration) { struct NameValueParserData pdata; struct UPNParg * GetPortMappingArgs; char * buffer; int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!intPort || !intClient || !extPort || !proto) return UPNPCOMMAND_INVALID_ARGS; GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); if(GetPortMappingArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; GetPortMappingArgs[0].elt = "NewRemoteHost"; GetPortMappingArgs[0].val = remoteHost; GetPortMappingArgs[1].elt = "NewExternalPort"; GetPortMappingArgs[1].val = extPort; GetPortMappingArgs[2].elt = "NewProtocol"; GetPortMappingArgs[2].val = proto; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "GetSpecificPortMappingEntry", GetPortMappingArgs, &bufsize); free(GetPortMappingArgs); if(!buffer) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewInternalClient"); if(p) { strncpy(intClient, p, 16); intClient[15] = '\0'; ret = UPNPCOMMAND_SUCCESS; } else intClient[0] = '\0'; p = GetValueFromNameValueList(&pdata, "NewInternalPort"); if(p) { strncpy(intPort, p, 6); intPort[5] = '\0'; } else intPort[0] = '\0'; p = GetValueFromNameValueList(&pdata, "NewEnabled"); if(p && enabled) { strncpy(enabled, p, 4); enabled[3] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); if(p && desc) { strncpy(desc, p, 80); desc[79] = '\0'; } p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); if(p && leaseDuration) { strncpy(leaseDuration, p, 16); leaseDuration[15] = '\0'; } p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(p, "%d", &ret); } ClearNameValueList(&pdata); return ret; }
LIBSPEC int UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * extPort, const char * inPort, const char * inClient, const char * desc, const char * proto, const char * remoteHost, const char * leaseDuration) { struct UPNParg * AddPortMappingArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; if(!inPort || !inClient || !proto || !extPort) return UPNPCOMMAND_INVALID_ARGS; AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); AddPortMappingArgs[0].elt = "NewRemoteHost"; AddPortMappingArgs[0].val = remoteHost; AddPortMappingArgs[1].elt = "NewExternalPort"; AddPortMappingArgs[1].val = extPort; AddPortMappingArgs[2].elt = "NewProtocol"; AddPortMappingArgs[2].val = proto; AddPortMappingArgs[3].elt = "NewInternalPort"; AddPortMappingArgs[3].val = inPort; AddPortMappingArgs[4].elt = "NewInternalClient"; AddPortMappingArgs[4].val = inClient; AddPortMappingArgs[5].elt = "NewEnabled"; AddPortMappingArgs[5].val = "1"; AddPortMappingArgs[6].elt = "NewPortMappingDescription"; AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; AddPortMappingArgs[7].elt = "NewLeaseDuration"; AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, &bufsize))) { free(AddPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ /*buffer[bufsize] = '\0';*/ /*puts(buffer);*/ ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); free(AddPortMappingArgs); return ret; }
MINIUPNP_LIBSPEC int UPNP_AddPinhole(const char * controlURL, const char * servicetype, const char * remoteHost, const char * remotePort, const char * intClient, const char * intPort, const char * proto, const char * leaseTime, char * uniqueID) { struct UPNParg * AddPinholeArgs; char * buffer; int bufsize; struct NameValueParserData pdata; const char * resVal; char * p; int ret; if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime) return UPNPCOMMAND_INVALID_ARGS; AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); if(AddPinholeArgs == NULL) return UPNPCOMMAND_MEM_ALLOC_ERROR; /* RemoteHost can be wilcarded */ if(strncmp(remoteHost, "empty", 5)==0) { AddPinholeArgs[0].elt = "RemoteHost"; AddPinholeArgs[0].val = ""; } else { AddPinholeArgs[0].elt = "RemoteHost"; AddPinholeArgs[0].val = remoteHost; } AddPinholeArgs[1].elt = "RemotePort"; AddPinholeArgs[1].val = remotePort; AddPinholeArgs[2].elt = "Protocol"; AddPinholeArgs[2].val = proto; AddPinholeArgs[3].elt = "InternalPort"; AddPinholeArgs[3].val = intPort; if(strncmp(intClient, "empty", 5)==0) { AddPinholeArgs[4].elt = "InternalClient"; AddPinholeArgs[4].val = ""; } else { AddPinholeArgs[4].elt = "InternalClient"; AddPinholeArgs[4].val = intClient; } AddPinholeArgs[5].elt = "LeaseTime"; AddPinholeArgs[5].val = leaseTime; buffer = simpleUPnPcommand(-1, controlURL, servicetype, "AddPinhole", AddPinholeArgs, &bufsize); free(AddPinholeArgs); if(!buffer) return UPNPCOMMAND_HTTP_ERROR; ParseNameValue(buffer, bufsize, &pdata); free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "UniqueID"); if(p) { strncpy(uniqueID, p, 8); uniqueID[7] = '\0'; } resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal);*/ ret = UPNPCOMMAND_UNKNOWN_ERROR; sscanf(resVal, "%d", &ret); } else { ret = UPNPCOMMAND_SUCCESS; } ClearNameValueList(&pdata); return ret; }
bool UPnP::start() { int error = 0; UPNPDev *devlist = ::upnpDiscover(2000, NULL, NULL, FALSE, FALSE, &error); UPNPDev *devlistBegin = devlist; // get interface list /*foreach(interface, interfaces) { newdevlist = ::upnpDiscover(2000, interface, NULL, FALSE, FALSE, &error); // go to end of list and append }*/ while (devlist) { UPNPUrls urls; IGDdatas data; char lanaddr[64]; UPnPHash resultHash; int code = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); if (code > 0) // TODO maybe distinguish between the return codes (1,2,3) to add information what happend to the result { resultHash.insert(LanIpAddress, QLatin1String(lanaddr)); char externalIP[40]; if (UPNPCOMMAND_SUCCESS == UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIP)) { resultHash.insert(ExternalIpAddress, QLatin1String(externalIP)); } char connectionType[64]; if (UPNPCOMMAND_SUCCESS == UPNP_GetConnectionTypeInfo(urls.controlURL, data.first.servicetype, connectionType)) { resultHash.insert(ConnectionType, QLatin1String(connectionType)); } quint32 uplink, downlink; if (UPNPCOMMAND_SUCCESS == UPNP_GetLinkLayerMaxBitRates(urls.controlURL_CIF, data.CIF.servicetype, &downlink, &uplink)) { resultHash.insert(LinkLayerMaxDownload, downlink); resultHash.insert(LinkLayerMaxUpload, uplink); } quint32 bytesSent, bytesReceived, packetsSent, packetsReceived; bytesSent = UPNP_GetTotalBytesSent(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != bytesSent) { resultHash.insert(TotalBytesSent, bytesSent); } bytesReceived = UPNP_GetTotalBytesReceived(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != bytesReceived) { resultHash.insert(TotalBytesReceived, bytesReceived); } packetsSent = UPNP_GetTotalPacketsSent(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != packetsSent) { resultHash.insert(TotalPacketsSent, packetsSent); } packetsReceived = UPNP_GetTotalPacketsReceived(urls.controlURL_CIF, data.CIF.servicetype); if ((unsigned int)UPNPCOMMAND_HTTP_ERROR != packetsReceived) { resultHash.insert(TotalPacketsReceived, packetsReceived); } char status[100]; unsigned int uptime = 0; char lastConnectionError[128]; if (UPNPCOMMAND_SUCCESS == UPNP_GetStatusInfo(urls.controlURL, data.first.servicetype, status, &uptime, lastConnectionError)) { resultHash.insert(Status, status); resultHash.insert(Uptime, uptime); resultHash.insert(LastConnectionError, lastConnectionError); } quint32 num; if (UPNPCOMMAND_SUCCESS == UPNP_GetPortMappingNumberOfEntries(urls.controlURL, data.first.servicetype, &num)) { resultHash.insert(NumberOfPortMappings, num); } // TODO GetListOfPortMappings do we need this? int firewallEnabled, inboundPinholeAllowed; if (UPNPCOMMAND_SUCCESS == UPNP_GetFirewallStatus(urls.controlURL, data.first.servicetype, &firewallEnabled, &inboundPinholeAllowed)) { resultHash.insert(FirewallEnabled, firewallEnabled); resultHash.insert(InboundPinholeAllowed, inboundPinholeAllowed); } int bufferSize = 0; if (char *buffer = (char *)miniwget(urls.rootdescURL, &bufferSize, 0)) { NameValueParserData pdata; ParseNameValue(buffer, bufferSize, &pdata); free(buffer); buffer = NULL; QStringList modelName = GetValuesFromNameValueList(&pdata, "modelName"); if (!modelName.isEmpty()) { resultHash.insert(ModelName, modelName.last()); } QStringList manufacturer = GetValuesFromNameValueList(&pdata, "manufacturer"); if (!manufacturer.isEmpty()) { resultHash.insert(Manufacturer, manufacturer.last()); } QStringList friendlyName = GetValuesFromNameValueList(&pdata, "friendlyName"); if (!friendlyName.isEmpty()) { resultHash.insert(FriendlyName, friendlyName.last()); } ClearNameValueList(&pdata); } } FreeUPNPUrls(&urls); results.append(resultHash); devlist = devlist->pNext; } freeUPNPDevlist(devlistBegin); emit finished(); return true; // TODO return false if something went wrong or if there are no results }