void FSE_GetResourceMetadata(void *fseObj, void *onQueryObj, /*INOUT*/ struct FSE_ResourceMetadata *res) { struct FSE_State* fse = (struct FSE_State*) fseObj; struct FSE_QueryState *qs = (struct FSE_QueryState*) onQueryObj; int dotPos, slashPos; /* * Return the fullpath name and the file size. */ if (res != NULL) { res->LocalFilePathLen = (int) strlen(qs->ProcessPath); res->LocalFilePath = (char*) malloc (res->LocalFilePathLen + 1); memcpy(res->LocalFilePath, qs->ProcessPath, res->LocalFilePathLen + 1); res->FileLength = qs->ProcessFileSize; slashPos = ILibString_LastIndexOf(res->LocalFilePath, res->LocalFilePathLen, fse->DirDelimiter, (int) strlen(fse->DirDelimiter)); dotPos = ILibString_LastIndexOf(res->LocalFilePath, res->LocalFilePathLen, ".", 1); if (qs->ProcessObjectType == FSE_OT_File) { res->Flags |= FSE_RMF_IsFile; if ((dotPos > 0) && (dotPos > slashPos)) { res->FileExtensionLen = res->LocalFilePathLen - dotPos; res->FileExtension = (char*) malloc(res->FileExtensionLen + 1); memcpy(res->FileExtension, res->LocalFilePath + dotPos, res->FileExtensionLen + 1); } } else { res->Flags |= FSE_RMF_IsDirectory; } } }
char* FilePathToFileExtension(char* file_path, int wide) { int slashPos; int dotPos; char* extension = NULL; int filePathLen = 0; if(file_path == NULL) return NULL; filePathLen = (int) strlen(file_path); slashPos = ILibString_LastIndexOf(file_path, filePathLen, WIN32_DIR_DELIMITER, WIN32_DIR_DELIMITER_LEN); dotPos = ILibString_LastIndexOf(file_path, filePathLen, ".", 1); if ((dotPos > 0) && (dotPos > slashPos)) { // this is a file int extensionLen = (int) strlen(file_path) - dotPos; extension = (char*) malloc(extensionLen + 1); memcpy(extension, file_path + dotPos, extensionLen + 1); return extension; } // this is a folder return NULL; }
int FSE_HandleProcessObject(void *fseObj, struct MSA_CdsQuery *cdsQuery, void *onQueryObj, unsigned int filter, /*INOUT*/ struct CdsObject *cdsObj) { struct FSE_State *fse = (struct FSE_State*) fseObj; struct FSE_QueryState *qs = (struct FSE_QueryState*) onQueryObj; struct FSE_PathInfo pi; struct FSE_ResourceMetadata* fseRes; int i; int expose = 0; int ignore = 0; char fn[MAX_FILENAME_SIZE]; fseRes = (struct FSE_ResourceMetadata*) malloc(sizeof(struct FSE_ResourceMetadata)); memset(fseRes, 0, sizeof(struct FSE_ResourceMetadata)); memset(&pi, 0, sizeof(struct FSE_PathInfo)); if (qs == NULL) { fprintf(stderr, "FSE_HandleProcessObject(): qs == NULL\r\n"); } if (cdsObj == NULL) { fprintf(stderr, "FSE_HandleProcessObject(): cdsObj == NULL\r\n"); } if ((qs->Flags & FSE_FLAG_Done) == 0) { /* * Do not process "." or ".." */ if ( (strcmp(qs->ProcessPath, "")==0) || (strcmp(qs->ProcessPath, ".")==0) || (strcmp(qs->ProcessPath, "..")==0) ) { ignore = 1; } /* get info about this path and determine if we're going to expose it */ if (ignore == 0) { /* * free temp storage */ if (pi.Ext != NULL) { free (pi.Ext); pi.Ext = NULL; pi.ExtLen = 0; } if (pi.FullPath != NULL) { free (pi.FullPath); pi.FullPath = NULL; pi.FullPathLen = 0; } if (pi.Name != NULL) { free (pi.Name); pi.Name = NULL; pi.NameLen = 0; } if (pi.NameNoExt != NULL) { free (pi.NameNoExt); pi.NameNoExt = NULL; pi.NameNoExtLen = 0; } if (pi.ParentPath != NULL) { free (pi.ParentPath); pi.ParentPath = NULL; pi.ParentPathLen = 0; } if (pi.RelativeFullPath != NULL) { free (pi.RelativeFullPath); pi.RelativeFullPath = NULL; pi.RelativeFullPathLen = 0; } if (pi.RelativeParent != NULL) { free (pi.RelativeParent); pi.RelativeParent = NULL; pi.RelativeParentLen = 0; } memset(&pi, 0, sizeof(struct FSE_PathInfo)); _FSE_ParsePathInfo(qs->ProcessPath, fse, qs, &pi); /* populate pi with data */ expose = _FSE_ExposeEntry(&pi, fse, qs); if(cdsQuery->QueryType == MSA_Query_BrowseMetadata) { qs->Flags |= FSE_FLAG_Done; } } /* * If this file is not supported, or it is a temp file where duplicated, we don't expose it, * we have to find the next valid entry. */ if (ignore == 1 || expose == 0) { expose = _FSE_FindNextEntry(fse, qs, &pi); } /* * SOLUTION_REFERENCE#3.6.3.2d */ if (expose != 0) { if(qs->CdsObjectType == FSE_CDS_PLAYSINGLE) { cdsObj->ID = (char*) malloc(pi.RelativeFullPathLen+CDS_STRING_PLAYSINGLE_ITEM_PREFIX_LEN+4); } else { cdsObj->ID = (char*) malloc(pi.RelativeFullPathLen+4); } cdsObj->ParentID = (char*) malloc(pi.RelativeParentLen+4); if (pi.RelativeFullPathLen > 0) { if(qs->CdsObjectType == FSE_CDS_PLAYSINGLE) { sprintf(cdsObj->ID, "%s0%s%s", CDS_STRING_PLAYSINGLE_ITEM_PREFIX, fse->DirDelimiter, pi.RelativeFullPath); } else { sprintf(cdsObj->ID, "0%s%s", fse->DirDelimiter, pi.RelativeFullPath); } if(ILibString_EndsWith(cdsObj->ID,(int)strlen(cdsObj->ID),EXTENSION_UPLOAD_TEMP,EXTENSION_UPLOAD_TEMP_LEN)!=0) { cdsObj->ID[(int)strlen(cdsObj->ID)-EXTENSION_UPLOAD_TEMP_LEN]=0; } if (pi.RelativeParentLen != 0) { sprintf(cdsObj->ParentID, "0%s%s", fse->DirDelimiter, pi.RelativeParent); } else { strcpy(cdsObj->ParentID, "0"); } } else { sprintf(cdsObj->ID, "0"); sprintf(cdsObj->ParentID, "-1"); } if(qs->ProcessObjectType == FSE_OT_Directory && pi.NameLen > 0) { /* this is a directory, use the full directory name */ cdsObj->Title = (char*) malloc(pi.NameLen+1); strcpy(cdsObj->Title, pi.Name); } else if (pi.NameNoExtLen > 0) { /* this is a file, use the name without extenstion for its title */ cdsObj->Title = (char*) malloc(pi.NameNoExtLen+1); strcpy(cdsObj->Title, pi.NameNoExt); if(qs->CdsObjectType == FSE_CDS_TEMPOPRARY) { /* remove actual file extension in front of the tmp file extension */ i = ILibString_LastIndexOf(cdsObj->Title, (int) strlen(cdsObj->Title),".",1); cdsObj->Title[i] = 0; } } else if ( (pi.RelativeFullPathLen == 0) && (pi.RelativeParentLen == pi.RelativeFullPathLen) ) { /* this is the root directory */ cdsObj->Title = (char*) malloc(5); strcpy(cdsObj->Title, "Root"); } else { /* unknown item */ cdsObj->Title = (char*) malloc(10); strcpy(cdsObj->Title, "<Unknown>"); } cdsObj->Source = (char*)malloc(pi.FullPathLen+1); memcpy(cdsObj->Source,pi.FullPath,pi.FullPathLen); cdsObj->Source[pi.FullPathLen]=0; cdsObj->DeallocateThese = CDS_ALLOC_ID | CDS_ALLOC_ParentID | CDS_ALLOC_Title; /* * Set the media class, the file system will consider the file type to be unknown if * the file extension is something it isn't aware of, so if we are processing * a temp file, then also need to find out its media class. */ if (qs->ProcessObjectType == FSE_OT_File) { if(strcmp(EXTENSION_UPLOAD_TEMP,pi.Ext)==0) { i = ILibString_LastIndexOf(pi.FullPath,pi.FullPathLen-EXTENSION_UPLOAD_TEMP_LEN,".",1); pi.FullPath[pi.FullPathLen-EXTENSION_UPLOAD_TEMP_LEN]=0; cdsObj->MediaClass = FileExtensionToClassCode(pi.FullPath+i, 0); pi.FullPath[pi.FullPathLen-EXTENSION_UPLOAD_TEMP_LEN]='.'; } else { cdsObj->MediaClass = FileExtensionToClassCode(pi.Ext, 0); } } else if (qs->ProcessObjectType == FSE_OT_Directory) { cdsObj->MediaClass = CDS_MEDIACLASS_STORAGEFOLDER; } else { /* * TODO: If you have other types of classes * you'll need to modify this section. */ cdsObj->MediaClass = CDS_MEDIACLASS_CONTAINER; } /* * CUSTOMIZE: Additional meta data for ITEM */ if ((cdsObj->MediaClass & CDS_CLASS_MASK_OBJECT_TYPE) == CDS_CLASS_MASK_ITEM) { /* * All items supports OCM: detroy item */ cdsObj->DlnaManaged = CDS_DlnaManaged_DestroyItem; /* If this is image/video item, then get the last modified timestamp of the file * and use it for the <dc:date> value */ switch (cdsObj->MediaClass & CDS_CLASS_MASK_MAJOR) { case CDS_CLASS_MASK_MAJOR_AUDIOITEM: cdsObj->TypeMajor.AudioItem.Date = (long) ILibFileDir_GetFileTimeStamp(cdsObj->Source); break; case CDS_CLASS_MASK_MAJOR_IMAGEITEM: cdsObj->TypeMajor.ImageItem.Date = (long) ILibFileDir_GetFileTimeStamp(cdsObj->Source); break; case CDS_CLASS_MASK_MAJOR_VIDEOITEM: cdsObj->TypeMajor.VideoItem.Date = (long) ILibFileDir_GetFileTimeStamp(cdsObj->Source); break; } #if defined (INCLUDE_FEATURE_PLAYSINGLE) /* * SOLUTION_REFERENCE#3.6.3.11a */ /* If playsingle simulation is enabled, and if it is a audio/image/video item, * then save the item's processpath, so that we'll use it to create a playsingle CdsObject */ if( (qs->CdsObjectType == FSE_CDS_NORMAL) && ( ((cdsObj->MediaClass & CDS_CLASS_MASK_MAJOR) == CDS_CLASS_MASK_MAJOR_AUDIOITEM) || ((cdsObj->MediaClass & CDS_CLASS_MASK_MAJOR) == CDS_CLASS_MASK_MAJOR_IMAGEITEM) || ((cdsObj->MediaClass & CDS_CLASS_MASK_MAJOR) == CDS_CLASS_MASK_MAJOR_VIDEOITEM) ) ) { strcpy(qs->PlaySingleProcessPath, qs->ProcessPath); } #endif } /* * CUSTOMIZE: Additional meta data for CONTAINER */ if ((cdsObj->MediaClass & CDS_CLASS_MASK_OBJECT_TYPE) == CDS_CLASS_MASK_CONTAINER) { /* * Containers are not searchable in this implementation. * CUSTOMIZE: Set this if container is searchable. * * cdsObj->Flags |= CDS_OBJPROP_FLAGS_Searchable; */ /* * Containers supports OCM: upload content and OCM: create child container, * DlnaManaged OCM: detroy item bit does not apply to containers */ cdsObj->DlnaManaged = CDS_DlnaManaged_UploadContent | CDS_DlnaManaged_CreateChildContainer; cdsObj->TypeObject.Container.ChildCount = 0; /* * Containers support OCM: content transfer must support <upnp:createClass> tag * This implemetation suppot audio, video and image items */ if(strncmp(cdsObj->ID, "0", strlen(cdsObj->ID))!=0) { cdsObj->TypeObject.Container.ChildCount = 3; /* set audioitem */ cdsObj->TypeObject.Container.CreateClass = (struct CdsCreateClass*) malloc(sizeof(struct CdsCreateClass)); memset(cdsObj->TypeObject.Container.CreateClass, 0, sizeof(struct CdsCreateClass)); cdsObj->TypeObject.Container.CreateClass->IncludeDerived=1; cdsObj->TypeObject.Container.CreateClass->MediaClass = CDS_MEDIACLASS_AUDIOITEM; /* set iamgeitem */ cdsObj->TypeObject.Container.CreateClass->Next = (struct CdsCreateClass*) malloc(sizeof(struct CdsCreateClass)); memset(cdsObj->TypeObject.Container.CreateClass->Next, 0, sizeof(struct CdsCreateClass)); cdsObj->TypeObject.Container.CreateClass->Next->IncludeDerived=1; cdsObj->TypeObject.Container.CreateClass->Next->MediaClass = CDS_MEDIACLASS_IMAGEITEM; /* set videoitem */ cdsObj->TypeObject.Container.CreateClass->Next->Next = (struct CdsCreateClass*) malloc(sizeof(struct CdsCreateClass)); memset(cdsObj->TypeObject.Container.CreateClass->Next->Next, 0, sizeof(struct CdsCreateClass)); cdsObj->TypeObject.Container.CreateClass->Next->Next->IncludeDerived=1; cdsObj->TypeObject.Container.CreateClass->Next->Next->MediaClass = CDS_MEDIACLASS_VIDEOITEM; /* set container */ cdsObj->TypeObject.Container.CreateClass->Next->Next->Next = (struct CdsCreateClass*) malloc(sizeof(struct CdsCreateClass)); memset(cdsObj->TypeObject.Container.CreateClass->Next->Next->Next, 0, sizeof(struct CdsCreateClass)); cdsObj->TypeObject.Container.CreateClass->Next->Next->Next->IncludeDerived=1; cdsObj->TypeObject.Container.CreateClass->Next->Next->Next->MediaClass = CDS_MEDIACLASS_CONTAINER; } } /* * This is a temp file, if the temp file was created from an upload request, * then the upload is incomplete, and we just expose the importUri value. * Since this is a file system, the only way to associate the importUri value * is faking it by regenerating the importUri value based on how the MSA object generated it * In a database backend, the application would call the MSA_ForCreateObjectResponse_AcceptUpload() method * which returns a request object, and you then call MSA_GetImportUri() to find out the importUri value and * store that in the database for the CDS item. */ // /* } /* * MUSTDO: Track the latest date as a means * for deriving the updateID for this entry */ /* * Track the number of entries we've processed. */ qs->ProcessIndex++; qs->CdsObjectType = FSE_CDS_NORMAL; /* * free temp storage */ if (pi.Ext != NULL) { free (pi.Ext); pi.Ext = NULL; pi.ExtLen = 0; } if (pi.FullPath != NULL) { free (pi.FullPath); pi.FullPath = NULL; pi.FullPathLen = 0; } if (pi.Name != NULL) { free (pi.Name); pi.Name = NULL; pi.NameLen = 0; } if (pi.NameNoExt != NULL) { free (pi.NameNoExt); pi.NameNoExt = NULL; pi.NameNoExtLen = 0; } if (pi.ParentPath != NULL) { free (pi.ParentPath); pi.ParentPath = NULL; pi.ParentPathLen = 0; } if (pi.RelativeFullPath != NULL) { free (pi.RelativeFullPath); pi.RelativeFullPath = NULL; pi.RelativeFullPathLen = 0; } if (pi.RelativeParent != NULL) { free (pi.RelativeParent); pi.RelativeParent = NULL; pi.RelativeParentLen = 0; } } if(fseRes->FileExtension!= NULL) {free(fseRes->FileExtension);} if(fseRes->LocalFilePath!= NULL) {free(fseRes->LocalFilePath);} free(fseRes); /* * finished populating the CDS Object for the file path, let's check if there's more files * in the directory to process, if so, update the QueringState object to prepare populating * the next CDS Object. */ if (qs->ProcessDirHandle != NULL) { while (ILibFileDir_GetDirNextFile( qs->ProcessDirHandle, qs->FilePath, fn, MAX_FILENAME_SIZE, &(qs->ProcessFileSize) ) != 0) { /* * A file was found. Let's see if it's something of interest. */ if (!((strcmp(fn, ".") == 0) || (strcmp(fn, "..") == 0))) { sprintf(qs->ProcessPath, "%s%s", qs->FilePath, fn); qs->ProcessObjectType = ILibFileDir_GetType(qs->ProcessPath); if( (qs->ProcessObjectType==ILibFileDir_Type_FILE) && (ILibString_EndsWith(qs->ProcessPath, (int) strlen(qs->ProcessPath), EXTENSION_UPLOAD_TEMP, EXTENSION_UPLOAD_TEMP_LEN)!=0) ) { /* treat incomplete upload files as CDS items. */ qs->CdsObjectType = FSE_CDS_TEMPOPRARY; } /* return the expose value for the current populated CDS Object */ return expose; } } #if defined (INCLUDE_FEATURE_PLAYSINGLE) /* * SOLUTION_REFERENCE#3.6.3.11b */ /* If playsingle simulation is enabled, then it will use the last valid CDS item and create * an additional CdsObject with a <res> element using the playsingle */ if(qs->CdsObjectType == FSE_CDS_NORMAL && qs->PlaySingleProcessPath[0] != '\0') { qs->CdsObjectType = FSE_CDS_PLAYSINGLE; /* replace the process path with the last valid CDS item process path. */ { strcpy(qs->ProcessPath, qs->PlaySingleProcessPath); qs->ProcessObjectType = ILibFileDir_GetType(qs->ProcessPath); qs->PlaySingleProcessPath[0] = '\0'; } } else { qs->CdsObjectType = FSE_CDS_NORMAL; #endif // no suitable entries were found, so mark it as being done qs->Flags |= FSE_FLAG_Done; #if defined (INCLUDE_FEATURE_PLAYSINGLE) } #endif } /* return the expose value for the current populated CDS Object */ return expose; }
void _FSE_ParsePathInfo(const char* fullpath, const struct FSE_State *fse, const struct FSE_QueryState *qs, /*INOUT*/ struct FSE_PathInfo *pi) { int len; int ddpos=0; int dotpos=0; /* free memory */ if (pi->Ext != NULL) { free (pi->Ext); pi->Ext = NULL; pi->ExtLen = 0; } if (pi->FullPath != NULL) { free (pi->FullPath); pi->FullPath = NULL; pi->FullPathLen = 0; } if (pi->Name != NULL) { free (pi->Name); pi->Name = NULL; pi->NameLen = 0; } if (pi->NameNoExt != NULL) { free (pi->NameNoExt); pi->NameNoExt = NULL; pi->NameNoExtLen = 0; } if (pi->ParentPath != NULL) { free (pi->ParentPath); pi->ParentPath = NULL; pi->ParentPathLen = 0; } if (pi->RelativeFullPath != NULL) { free (pi->RelativeFullPath); pi->RelativeFullPath = NULL; pi->RelativeFullPathLen = 0; } if (pi->RelativeParent != NULL) { free (pi->RelativeParent); pi->RelativeParent = NULL; pi->RelativeParentLen = 0; } len = (int) strlen(fullpath); pi->FullPath = (char*) malloc(len+2); memcpy(pi->FullPath, fullpath, len); pi->FullPath[len] = '\0'; pi->FullPathLen = len; /* * If it's a directory, make sure it ends * with a trailing directory delimiter. * We do this because fse->RootPath will have * a trailing delimiter. */ if ( (qs->ProcessObjectType == FSE_OT_Directory) && (pi->FullPath[pi->FullPathLen-1] != fse->DirDelimiterChr) ) { pi->FullPath[pi->FullPathLen] = fse->DirDelimiterChr; pi->FullPathLen++; pi->FullPath[pi->FullPathLen] = '\0'; } /* * Get the relative full path. */ pi->RelativeFullPathLen = pi->FullPathLen - fse->RootPathLen; pi->RelativeFullPath = (char*) malloc (pi->RelativeFullPathLen + 1); memcpy(pi->RelativeFullPath, pi->FullPath + fse->RootPathLen, pi->RelativeFullPathLen); pi->RelativeFullPath[pi->RelativeFullPathLen] = '\0'; /* * Find last directory delimiter. * If the fullpath is a directory, temporarily * terminate w/o a trailing delimiter. */ if (qs->ProcessObjectType == FSE_OT_Directory) { pi->FullPathLen--; pi->FullPath[pi->FullPathLen] = '\0'; } ddpos = ILibString_LastIndexOf(pi->FullPath, pi->FullPathLen, fse->DirDelimiter, (int) strlen(fse->DirDelimiter)); if (qs->ProcessObjectType == FSE_OT_Directory) { pi->FullPath[pi->FullPathLen] = fse->DirDelimiterChr; pi->FullPathLen++; } /* * Get the name of the directory/file. * If no directory delimiter was found, * there is no name... which indicates * we should treat it as the root. */ if (ddpos >= 0) { pi->NameLen = pi->FullPathLen - ddpos - 1; pi->Name = (char*) malloc(pi->NameLen+1); memcpy(pi->Name, pi->FullPath + ddpos + 1, pi->NameLen+1); } else { pi->NameLen = 0; pi->Name = (char*) malloc(1); pi->Name[0] = '\0'; } /* * Chop a trailing dir delimiter. */ if ( (pi->NameLen > 0) && (pi->Name[pi->NameLen-1] == fse->DirDelimiterChr) ) { pi->NameLen--; pi->Name[pi->NameLen] = '\0'; } dotpos = ILibString_LastIndexOf(pi->Name, pi->NameLen, ".", 1); if (dotpos >= 0) { /* * Get the name w/o the extension and save extension. */ pi->NameNoExtLen = dotpos; pi->NameNoExt = (char*) malloc(pi->NameNoExtLen + 1); memcpy(pi->NameNoExt, pi->Name, pi->NameNoExtLen); pi->NameNoExt[pi->NameNoExtLen] = '\0'; pi->ExtLen = pi->NameLen - pi->NameNoExtLen; pi->Ext = (char*) malloc (pi->ExtLen + 1); memcpy(pi->Ext, pi->Name + dotpos, pi->ExtLen+1); } else { /* * Name w/o extension is the same as name. * Extension is blank. */ pi->NameNoExt = (char*) malloc(pi->NameLen+1); memcpy(pi->NameNoExt, pi->Name, pi->NameLen+1); pi->NameNoExtLen = pi->NameLen; pi->ExtLen = 0; pi->Ext = (char*) malloc(pi->ExtLen+1); pi->Ext[0] = '\0'; } /* * Get the parent directory name */ if (ddpos >= 0) { pi->ParentPathLen = ddpos+1; pi->ParentPath = (char*) malloc(pi->ParentPathLen+1); memcpy(pi->ParentPath, pi->FullPath, pi->ParentPathLen); pi->ParentPath[pi->ParentPathLen] = '\0'; } else { pi->ParentPathLen = 0; pi->ParentPath = (char*) malloc(1); pi->ParentPath[0] = '\0'; } /* * Get the relative parent dir. * rootlen includes a trailinger dir delimiter. */ if ((pi->ParentPathLen > 0) && (pi->ParentPathLen >= fse->RootPathLen)) { pi->RelativeParentLen = pi->ParentPathLen - fse->RootPathLen; pi->RelativeParent = (char*) malloc(pi->RelativeParentLen + 1); memcpy(pi->RelativeParent, pi->ParentPath + fse->RootPathLen, pi->RelativeParentLen); pi->RelativeParent[pi->RelativeParentLen] = '\0'; } else { pi->RelativeParentLen = 0; pi->RelativeParent = (char*) malloc(1); pi->RelativeParent[0] = '\0'; } }