int FSE_RelativePathToLocalFilePath(void *fseObj, const char *relativePath, int relativePathLen, char *localFilePath) { struct FSE_State* fse = (struct FSE_State*) fseObj; int RetVal; char *tempString; tempString = ILibString_Replace(relativePath,relativePathLen,"/",1,"\\",1); relativePath = (const char*)tempString; if(ILibString_StartsWith(relativePath,relativePathLen,"\\",1)!=0) { relativePath += 1; relativePathLen -= 1; } RetVal = relativePathLen+fse->RootPathLen; memcpy(localFilePath,fse->RootPath,fse->RootPathLen); memcpy(localFilePath+fse->RootPathLen,relativePath,relativePathLen); localFilePath[RetVal]=0; free(tempString); return(RetVal); }
BOOL ParsePlayContainerUri(PlayListManager_PC state, char* uri) { struct parser_result_field* field; struct parser_result* parseResults; int length; char* pos = NULL; char* tmp = NULL; uri = PC_UriUnescape(uri); pos = uri + 21; if(ILibString_StartsWith(uri, (int)strlen(uri), "dlna-playcontainer://", 21) == 0) { free(uri); return FALSE; } if(ILibString_StartsWithEx(pos, (int)strlen(pos), "uuid:", 5, 0) != 0) { pos += 5; } { char out[4096]; sprintf(out, "%s\n", pos); OutputDebugString(out); } tmp = MyStrChr(pos, 0x003f); { char out[4096]; sprintf(out, "%s\n", tmp); OutputDebugString(out); } if(tmp == NULL) { free(uri); return FALSE; } length = (int)(tmp - pos); String_Destroy(state->UDN); state->UDN = String_CreateSize(length); strncpy(state->UDN, pos, (size_t)length); state->UDN[length] = 0; if(state->UDN[length - 1] == '/') { state->UDN[length - 1] = 0; } pos += length + 1; parseResults = ILibParseString(pos, 0, (int)strlen(pos), "&", 1); state->FirstItemIndex = -1; field = parseResults->FirstResult; while(field != NULL) { int length; char* val = field->data; if(ILibString_StartsWith(field->data, field->datalength, "sid=", 4) != 0) { length = field->datalength - 4; val += 4; String_Destroy(state->ServiceID); state->ServiceID = String_CreateSize(length); strncpy(state->ServiceID, val, (size_t)length); state->ServiceID[length] = 0; } else if(ILibString_StartsWith(field->data, field->datalength, "cid=", 4) != 0) { length = field->datalength - 4; val += 4; String_Destroy(state->ContainerID); state->ContainerID = String_CreateSize(length); strncpy(state->ContainerID, val, (size_t)length); state->ContainerID[length] = 0; } else if(ILibString_StartsWith(field->data, field->datalength, "fid=", 4) != 0) { length = field->datalength - 4; val += 4; String_Destroy(state->FirstItemID); state->FirstItemID = String_CreateSize(length); strncpy(state->FirstItemID, val, (size_t)length); state->FirstItemID[length] = 0; } else if(ILibString_StartsWith(field->data, field->datalength, "fii=", 4) != 0) { char* tmp = NULL; length = field->datalength - 4; val += 4; tmp = String_CreateSize(length); strncpy(tmp, val, length); tmp[length] = 0; state->FirstItemIndex = atoi(tmp); String_Destroy(tmp); } else if(ILibString_StartsWith(field->data, field->datalength, "sc=", 3) != 0) { length = field->datalength - 3; val += 3; String_Destroy(state->SortArgs); state->SortArgs = String_CreateSize(length); strncpy(state->SortArgs, val, (size_t)length); state->SortArgs[length] = 0; } else if(ILibString_StartsWith(field->data, field->datalength, "md=", 3) != 0) { char* tmp = NULL; length = field->datalength - 3; val += 3; tmp = String_CreateSize(length); strncpy(tmp, val, length); tmp[length] = 0; state->MaxDepth = atoi(tmp); String_Destroy(tmp); } else { String_Destroy(state->UDN); String_Destroy(state->ServiceID); String_Destroy(state->ContainerID); String_Destroy(state->FirstItemID); String_Destroy(state->SortArgs); ILibDestructParserResults(parseResults); return FALSE; } field = field->NextResult; } ILibDestructParserResults(parseResults); if(state->ServiceID != NULL && state->ContainerID != NULL && state->FirstItemID != NULL && state->FirstItemIndex != -1) { free(uri); return TRUE; } else { String_Destroy(state->UDN); String_Destroy(state->ServiceID); String_Destroy(state->ContainerID); String_Destroy(state->FirstItemID); String_Destroy(state->SortArgs); free(uri); return FALSE; } }
int FSE_HandleCreateObject(void *fseObj, struct MSA_CdsCreateObj *createObjArg, struct DLNAProtocolInfo* protocolInfo, struct CdsObject *newCdsObject) { struct FSE_State* fse = (struct FSE_State*)fseObj; char* id = NULL; char* parentId = NULL; char* title = NULL; int size; int retVal = 0; int parentIdLen = 0; if(newCdsObject != NULL) { parentId = DecodeFromUTF8(newCdsObject->ParentID); parentIdLen = (int) strlen(parentId); if((newCdsObject->MediaClass & CDS_CLASS_MASK_OBJECT_TYPE) == CDS_CLASS_MASK_CONTAINER) { /* this is a container, so the file system will create a new folder */ char* rootPath = NULL; int i, len = 0; char* folder = NULL; if(newCdsObject->Title != NULL) { rootPath = fse->RootPath; title = DecodeFromUTF8(newCdsObject->Title); len = (int)strlen(title) + (int)strlen(rootPath) + parentIdLen; folder = malloc(len + 1); strcpy(folder, rootPath); if(ILibString_StartsWith(parentId, parentIdLen, "0\\", 2)!=0 && parentIdLen>2) { strcat(folder, parentId + 2); // skip directory 0 } else if(strnicmp(parentId, CDS_STRING_DLNA_ANYCONTAINER, CDS_STRING_DLNA_ANYCONTAINER_LEN)==0) { // ToDo: how to handle AnyContainer uploads // for now it reset to the root directory of the CDS. free(parentId); parentId = ILibString_Copy("0\\", -1); } strcat(folder, title); for(i = 0; i < len; i++) { if(folder[i] == '/') { folder[i] = '\\'; } } retVal = ILibFileDir_CreateDir(folder); free(folder); } } else { /* this is an item, the file system will map the item to a local file, and return the corresponding object ID */ char* rootPath = NULL; char* fileExtension = NULL; char* extension = NULL; int i, len = 0; char* file = NULL; char* tmp = NULL; rootPath = fse->RootPath; if(newCdsObject->Title != NULL) { title = DecodeFromUTF8(newCdsObject->Title); } else { int num = rand() % 1000000000; title = (char*) malloc(15); sprintf(title, "file%d", num); } /* we cannot rely on the title of the Cds Item to determine its media type, but rather its DLNA Profile */ switch(newCdsObject->MediaClass & CDS_CLASS_MASK_MAJOR) { case CDS_CLASS_MASK_MAJOR_AUDIOITEM: if(strcmp(protocolInfo->Profile, DLNAPROFILE_LPCM)==0) { extension = EXTENSION_AUDIO_LPCM; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_MP3)==0) { extension = EXTENSION_AUDIO_MPEG; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_AMR_3GPP)==0) { extension = EXTENSION_AUDIO_3GPP; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_AAC_ISO_320)==0) { extension = EXTENSION_AUDIO_AAC; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_WMABASE)==0) { extension = EXTENSION_AUDIO_WMA; } else { /* not supported */ } break; case CDS_CLASS_MASK_MAJOR_IMAGEITEM: if(strcmp(protocolInfo->Profile, DLNAPROFILE_JPEG_SM)==0) { extension = EXTENSION_IMAGE_JPG; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_JPEG_MED)==0) { extension = EXTENSION_IMAGE_JPG; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_JPEG_LRG)==0) { extension = EXTENSION_IMAGE_JPG; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_PNG_LRG)==0) { extension = EXTENSION_IMAGE_PNG; } else { /* not supported */ } break; case CDS_CLASS_MASK_MAJOR_VIDEOITEM: if(strcmp(protocolInfo->Profile, DLNAPROFILE_MPEG_PS_NTSC)==0) { extension = EXTENSION_VIDEO_MPEG2; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_AVC_MP4_BL_CIF15_AAC_520)==0) { extension = EXTENSION_VIDEO_AAC; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_MPEG_PS_NTSC)==0) { extension = EXTENSION_VIDEO_MPEG2; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_MPEG4_P2_ASF_SP_G726)==0) { extension = EXTENSION_VIDEO_ASF; } else if(strcmp(protocolInfo->Profile, DLNAPROFILE_WMVMED_BASE)==0) { extension = EXTENSION_VIDEO_WMV; } else { /* not supported */ } break; } if(extension == NULL) { /* no valid extension found, not a valid media item */ return -1; } /* replace file extension with the valid extension found */ fileExtension = FilePathToFileExtension(title, 0); if(fileExtension != NULL) { tmp = title; /* replace old title with new title with correct extension */ title = ILibString_Replace( title, (int) strlen(title), fileExtension, (int) strlen(fileExtension), extension, (int) strlen(extension)); free(fileExtension); free(tmp); } else { tmp = (char*) malloc((int) strlen(title) + (int) strlen(extension) + 1); strcpy(tmp, title); strcat(tmp, extension); free(title); title = tmp; } /* replace old title with UTF-8 encoded title */ if (newCdsObject->DeallocateThese & CDS_ALLOC_Title) { free(newCdsObject->Title); } newCdsObject->Title = EncodeToUTF8(title); len = (int)strlen(title) + (int)strlen(rootPath) + parentIdLen; file = malloc(len + 1); strcpy(file, rootPath); if(ILibString_StartsWith(parentId, parentIdLen, "0\\", 2)!=0 && parentIdLen>2) { strcat(file, parentId + 2); // skip directory 0 } else if(strnicmp(parentId, CDS_STRING_DLNA_ANYCONTAINER, CDS_STRING_DLNA_ANYCONTAINER_LEN)==0) { // ToDo: how to handle AnyContainer uploads // for now it reset to the root directory of the CDS. free(parentId); parentId = ILibString_Copy("0\\", -1); } strcat(file, title); for(i = 0; i < len; i++) { if(file[i] == '/') { file[i] = '\\'; } } /* Finds out if there's already a uploaded object */ tmp = (char*) malloc(strlen(file) + EXTENSION_UPLOAD_TEMP_LEN + 1); strcpy(tmp, file); strcat(tmp, EXTENSION_UPLOAD_TEMP); if(ILibFileDir_GetType(tmp) == FSE_OT_NoExist) { /* temp file does not exists, no file is currently being uploaded */ retVal = 0; /* overwriting the file, remove the old file in order to avoid duplicates in CDS*/ ILibFileDir_DeleteFile(file); newCdsObject->Source = ILibString_Copy(tmp,-1); } else { retVal = -1; } free(file); free(tmp); } } // replace requested object ID with the correct object ID; if ((newCdsObject->ParentID != NULL) && (newCdsObject->DeallocateThese & CDS_ALLOC_ParentID)) { // free previous parentId free(newCdsObject->ParentID); } newCdsObject->ParentID = EncodeToUTF8(parentId); if((newCdsObject->ID != NULL) && (newCdsObject->DeallocateThese & CDS_ALLOC_ID)) { free(newCdsObject->ID); } size = parentIdLen + (int) strlen(title) + 2; id = (char*) malloc (size); strcpy(id, parentId); if(ILibString_EndsWith(parentId, parentIdLen, "\\", 1)!=0) { strcat(id, "\\"); } strcat(id, title); newCdsObject->ID = EncodeToUTF8(id); newCdsObject->DeallocateThese |= CDS_ALLOC_ParentID; newCdsObject->DeallocateThese |= CDS_ALLOC_ID; if(id!=NULL) free(id); if(parentId!=NULL) free(parentId); if(title!=NULL) free(title); return retVal; }
DH_TransferStatus DHS_RespondWithLocalFile(struct ILibWebServer_Session *session, ILibThreadPool pool, struct packetheader *header, size_t buffer_size, const char *file_name, unsigned int supported_transfer_mode, const char *mime_type, const char *content_features, const char* ifo_uri, void *user_obj, DHS_OnResponseDone callback_response) { DH_TransferStatus retval = NULL; FILE *f; struct DH_Data *data = NULL; struct packetheader *resp = NULL; char *ifo, *cf = NULL; long RangeStart,RangeLength,FileLength; char len[255]; enum ILibWebClient_Range_Result RangeResult = 0; enum DH_TransferModes transferMode; if(session->done==0) { // // If the get request wasn't completely received yet, then we don't need to do anything yet // return NULL; } f = fopen(file_name,"rb"); if(f!=NULL) { data = (struct DH_Data*)malloc(sizeof(struct DH_Data)); memset(data,0,sizeof(struct DH_Data)); resp = ILibCreateEmptyPacket(); ILibSetVersion(resp,"1.1",3); fseek(f,0,SEEK_END); FileLength = ftell(f); fseek(f,0,SEEK_SET); cf = ILibGetHeaderLine(header,"getcontentFeatures.dlna.org",27); if(cf!= NULL && memcmp(cf, "1", 1)!=0) { ILibWebServer_Send_Raw(session,"HTTP/1.1 400 Bad Request\r\n\r\n",28,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } transferMode = DH_GetRequestedTransferMode(header); if( ((transferMode == DH_TransferMode_Bulk) || (transferMode == DH_TransferMode_Interactive)) && ((ILibGetHeaderLine(header,"TimeSeekRange.dlna.org",22)!=NULL) || (ILibGetHeaderLine(header,"PlaySpeed.dlna.org",18)!=NULL) || (ILibGetHeaderLine(header,"realTimeInfo.dlna.org",21)!=NULL) ) ) { ILibWebServer_Send_Raw(session,"HTTP/1.1 400 Bad Request\r\n\r\n",28,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } if(ILibGetHeaderLine(header,"Range",5)!=NULL) { RangeResult = ILibWebClient_Parse_Range(ILibGetHeaderLine(header,"Range",5),&RangeStart,&RangeLength,FileLength); switch(RangeResult) { case ILibWebClient_Range_Result_OK: fseek(f,RangeStart,SEEK_SET); data->BytesLeft = RangeLength; ILibSetStatusCode(resp,206,"Partial Content",15); DH_AddHeader_ContentRange(resp,RangeStart,(RangeStart+RangeLength)-1,FileLength); break; case ILibWebClient_Range_Result_INVALID_RANGE: ILibWebServer_Send_Raw(session,"HTTP/1.1 416 Invalid Range\r\n\r\n",30,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); break; case ILibWebClient_Range_Result_BAD_REQUEST: ILibWebServer_Send_Raw(session,"HTTP/1.1 400 Bad Request\r\n\r\n",28,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); break; } } else if(ILibGetHeaderLine(header,"TimeSeekRange.dlna.org",22)!=NULL) { ILibWebServer_Send_Raw(session,"HTTP/1.1 406 Time-based seek not supported\r\n\r\n",46,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } else if(ILibGetHeaderLine(header,"PlaySpeed.dlna.org",18)!=NULL) { ILibWebServer_Send_Raw(session,"HTTP/1.1 406 PlaySpeeds not supported\r\n\r\n",41,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } else { ILibSetStatusCode(resp,200,"OK",2); data->BytesLeft = FileLength; sprintf(len,"%ld",data->BytesLeft); ILibAddHeaderLine(resp,"Content-Length",14,len,(int)strlen(len)); ILibAddHeaderLine(resp,"Accept-Ranges",13,"bytes",5); } if(transferMode == DH_TransferMode_Unspecified && mime_type != NULL) { if(ILibString_StartsWith(mime_type, (int) strlen(mime_type), "video/", 6) != 0) { DH_AddHeader_transferMode(resp, DH_TransferMode_Streaming); } else if(ILibString_StartsWith(mime_type, (int) strlen(mime_type), "audio/", 6) != 0) { DH_AddHeader_transferMode(resp, DH_TransferMode_Streaming); } else if(ILibString_StartsWith(mime_type, (int) strlen(mime_type), "image/", 6) != 0) { DH_AddHeader_transferMode(resp, DH_TransferMode_Interactive); } } else if(!(transferMode & supported_transfer_mode)) { // // Specified transfer mode is not supported // ILibWebServer_Send_Raw(session,"HTTP/1.1 406 Not Acceptable\r\n\r\n",31,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(f); free(data); ILibDestructPacket(resp); return(NULL); } else { DH_AddHeader_transferMode(resp,transferMode); } data->callback_response = callback_response; data->f = f; data->header = header; data->session = session; data->pool = pool; data->TransferStatus = retval = DH_CreateNewTransferStatus(); data->TransferStatus->TotalBytesToBeSent = data->BytesLeft; data->user_object = user_obj; retval->ServerSession = session; session->OnDisconnect = &DH_Disconnect; if(content_features!=NULL) { ILibAddHeaderLine(resp,"contentFeatures.dlna.org",24,(char*) content_features,(int)strlen(content_features)); } if(mime_type!=NULL) { ILibAddHeaderLine(resp,"Content-Type",12,(char*)mime_type,(int)strlen(mime_type)); } else { ILibAddHeaderLine(resp,"Content-Type",12,(char*)DHS_DEFAULT_MIMETYPE,(int)strlen(DHS_DEFAULT_MIMETYPE)); } if(ifo_uri!=NULL) { ifo = (char*)malloc((int)strlen(ifo_uri)+25); sprintf(ifo,"ifoFileURI.dlna.org=\"%s\"",ifo_uri); ILibAddHeaderLine(resp,"PRAGMA",6,ifo,(int)strlen(ifo)); free(ifo); } ILibWebServer_StreamHeader(session,resp); if(header->DirectiveLength==4 && strncasecmp(header->Directive,"HEAD",4)==0) { ILibWebServer_StreamBody(session,NULL,0,ILibAsyncSocket_MemoryOwnership_STATIC,1); fclose(data->f); data->f = NULL; DH_DestroyTransferStatus(data->TransferStatus); free(data); session->OnDisconnect = NULL; return(NULL); } else { lock_init(&(data->SendStatusLock),0,1); ILibThreadPool_QueueUserWorkItem(pool,data,&DH_Pool); } } else { // // Error opening file // ILibWebServer_Send_Raw(session,"HTTP/1.1 404 File Not Found\r\n\r\n",31,ILibAsyncSocket_MemoryOwnership_STATIC,1); } return retval; }
struct _PlaySingleUri* _ParsePlaySingleUri(char* playSingleURI) { struct _PlaySingleUri* result = NULL; size_t allocSize = 0; char* pos = NULL; if(playSingleURI == NULL || ILibString_StartsWith(playSingleURI, (int)strlen(playSingleURI), "dlna-playsingle://", 18) == 0) { return NULL; } allocSize = strlen(playSingleURI) + sizeof(struct _PlaySingleUri) + 1; result = (struct _PlaySingleUri*)malloc(strlen(playSingleURI) + sizeof(struct _PlaySingleUri) + 1); memset(result, 0, allocSize); result->Method = (char*)result + sizeof(struct _PlaySingleUri); strcpy(result->Method, playSingleURI); pos = strchr(result->Method, (int)':'); if(pos == NULL) { free(result); return NULL; } *pos = '\0'; pos += 3; result->UDN = pos; pos = strchr(pos, (int)'?'); if(pos == NULL) { free(result); return NULL; } *pos = '\0'; if(*(pos-1) == '/') { *(pos-1) = '\0'; } pos++; result->ServiceID = pos; pos = strchr(pos, (int)'&'); if(pos == NULL) { free(result); return NULL; } *pos = '\0'; pos++; result->ItemID = pos; result->ServiceID = strchr(result->ServiceID, '='); result->ItemID = strchr(result->ItemID, '='); if(result->ItemID == NULL || result->ServiceID == NULL) { free(result); return NULL; } result->ItemID++; result->ServiceID++; ILibInPlaceHTTPUnEscape(result->ItemID); ILibInPlaceHTTPUnEscape(result->UDN); ILibInPlaceHTTPUnEscape(result->ServiceID); return result; }