chxavfileutil.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:32k
- /*****************************************************************************
- * chxavfileutil.h
- * ---------------
- *
- * Synopsis:
- * File utility namespace. Misc stuff for helping to work with filenames and
- * paths.
- *
- * Target:
- * Symbian OS
- *
- *
- * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
- *
- *****************************************************************************/
- // Symbian includes...
- #include <eikfutil.h>
- #include <f32file.h>
- #include <apgcli.h>
- #include <apmrec.h>
- #include <sysutil.h>
- #include <eikappui.h>
- #include <eikapp.h>
- // Helix includes...
- #include "hxtypes.h"
- #include "hxassert.h"
- #include "hxcom.h"
- #include "hxprefs.h" //IHXPreferences
- // Include from this project...
- #include "chxavutil.h"
- #include "chxavfileutil.h"
- #include "chxavcleanstring.h"
- #include "chxavutil.h"
- #include "chxavescapedstring.h"
- #include "chxavdirectoryreader.h"
- #include "chxavcleanupstack.h"
- #include "hxsym_debug.h"
- #include "hxapihelp.h"
- #include "hxsym_leaveutil.h"
- #include "hxsym_filetype.h"
- #include "hxsym_mimetypes.h"
- namespace CHXAvFile
- {
- // explictly instanciate GetFolderChildCount template here
- template
- TInt GetFolderChildCount(const TDesC& folderPath,
- TInt& countOut, bool bWantFolders,
- PFNNanoPlayerFilterType isWantedFile);
- ////////////////////////////////////////////////////
- // get number of folders and files immediately within the
- // given directory (not recursive)
- //
- template <typename FileFilter>
- TInt GetFolderChildCount(const TDesC& folderPath,
- TInt& countOut, bool bWantFolders,
- FileFilter isWantedFile)
- {
- RFs& fs = CCoeEnv::Static()->FsSession();
- CHXAvDirectoryReader reader(fs);
- TInt error = KErrNone;
- countOut = -1;
- reader.SetSortFlags(ESortNone); // be as fast as possible; don't need sorting here
- if( reader.SetToPath(folderPath) )
- {
- countOut = 0;
- const CDir* pFiles = reader.GetFiles();
- if(pFiles)
- {
- // only count files that are of interest and not hidden
- TInt count = pFiles->Count();
- for(TInt idx = 0; idx < count; ++idx)
- {
- TEntry entry = (*pFiles)[idx];
- if( !CHXAvUtil::ShouldHideFromUser(entry) && isWantedFile(folderPath, entry.iName) )
- {
- ++countOut;
- }
- }
- pFiles = 0;
- }
- if( bWantFolders )
- {
- const CDir* pFolders = reader.GetDirs();
- if(pFolders)
- {
- // add non-hidden directories to total
- TInt count = pFolders->Count();
- for(TInt idx = 0; idx < count; ++idx)
- {
- TEntry entry = (*pFolders)[idx];
- if( !CHXAvUtil::ShouldHideFromUser(entry) )
- {
- countOut += 1;
- }
- }
-
- }
- }
- }
- else
- {
- error = reader.GetLastError();
- }
- return error;
- }
- bool IsNanoPlayerFileType(const TDesC& fullPath)
- {
- FileType fileType = GetFileType(fullPath);
- return IsNanoPlayerFileType(fileType);
- }
- bool IsNanoPlayerFileType(const TDesC& folderPath, const TDesC& itemName)
- {
- TFileName* fullPath = AllocFileNameL(folderPath, itemName);
- AUTO_PUSH_POP_DEL(fullPath);
- FileType fileType = GetFileType(*fullPath);
- return IsNanoPlayerFileType(fileType);
- }
- ////////////////////////////////
- // get fully qualified absolute path (with drive letter prefix), ensuring that it
- // exists
- //
- // searches all available drives: first session drive (normally 'c:'), then y to a, then z
- //
- // if a drive letter is supplied, only that drive will be searched; other
- // drives are not searched
- //
- // Parameters:
- //
- // path - absolute (with drive) or relative (to unspecified drive) path;
- // must have folder suffix if a folder is wanted
- // fullPath - fully qualified absolute and verified path (with drive letter prefix)
- // if return is KErrNone
- //
- // bAllowWildCard - returns first match if true (even if multiple matches!)
- //
- TInt GetFullPath(RFs& fs, const TDesC& path, TDes& fullPath, bool bAllowWildCard)
- {
- DPRINTF(SYMP_FILE, ("CHXAvFile::GetFullPath(): looking for '%s'n", dbg::CharPtr(path)()));
- TInt err = KErrNotFound;
- fullPath = KNullDesC;
-
- TInt idxDrive = GetDriveIndex(path);
- if( (-1 != idxDrive) && path.Length() <= 3 )
- {
- //
- // special case: confirming that drive root path (e.g. 'e:') exists
- //
- // TFileFind fails if we specify root path
- //
- if(PathExists(path))
- {
- fullPath = path;
- err = KErrNone;
- }
- }
- else
- {
- TFindFile find(fs);
-
- CDir* pDir = 0;
- if(bAllowWildCard)
- {
- // search for first match
- err = find. FindWildByDir(path, KNullDesC, pDir);
- }
- else
- {
- err = find.FindByDir(path, KNullDesC);
- }
- if (err == KErrNone)
- {
- if(pDir)
- {
- fullPath = GetFolderPath(find.File());
- if( pDir->Count() > 0 )
- {
- // File() returns drive and path in this case; set returned path to first entry found
- fullPath.Append( (*pDir)[0].iName );
- }
- HX_DELETE(pDir);
- }
- else
- {
- fullPath = find.File();
- }
- // if drive was specified for sought-after path, ensure found path matches
-
- if( idxDrive != -1 )
- {
- //
- // TFindFile will search for path on an alternate drive
- // if it fails to find a path on a specified drive; it treats drive letter
- // as meaning 'preferred' as opposed to 'required' (as we do)
- //
- TInt idxDriveFound = GetDriveIndex(fullPath);
- if(idxDriveFound != idxDrive)
- {
- // path doesn't exist on drive we wanted; refuse path on alternate drive
- fullPath = KNullDesC;
- err = KErrNotFound;
- }
- }
- }
- }
-
- DPRINTF(SYMP_FILE, ("GetFullPath(): found '%s'n", dbg::CharPtr(fullPath)()));
- return err;
- }
- ////////////////////////////////////////////////////////
- // alloc default name; append (N) to name until name is unique
- // within the path
- //
- // defaultName - name of file or folder to begin with ('name' or 'name/')
- // basePath - full base path
- //
- // e.g., New Folder, New Folder(01), New Folder(02)
- //
- // returns 0 if:
- // a) no unique name could be found (bad base path or roque tester);
- // b) not enough space to fit suggested name plus prefix (base path + default name near max TFileName)
- //
- // XXXLCM consider using CApaApplication::GenerateFileName
- //
- TFileName* AllocUniqueDefaultNameL(const TDesC& basePath,
- const TDesC& defaultName,
- bool bWantFolder,
- const CHXAvNameDisplayTrait& nameTrait)
- {
- _LIT(KDuplicateNameFormat, "%S(%02d)");
- const TUint k_cchSuffix = 4; //"(NN)"
- const TUint k_maxTries = 100;
- TFileName* pPathOut = 0;
-
- // make sure we have a qualified name (indicating folder or file)
- TFileName* pFullDefaultName = AllocFileNameL(defaultName, (bWantFolder ? CHXAvFile::ntFolder : CHXAvFile::ntFile));
- AUTO_PUSH_POP_DEL(pFullDefaultName);
- // break up qualified name for display and formatting
- NameExt nameInfo = nameTrait.GetDisplayText(*pFullDefaultName, bWantFolder);
- // max chars for 'name' in 'name.xx'
- TInt cchMaxNamePart = KMaxFileName - basePath.Length() - nameInfo.second.Length();
- if( !HasFolderSuffix(basePath) )
- {
- cchMaxNamePart -= 1; // for path sep that would be added to form full path
- }
- if ( cchMaxNamePart > 0 )
- {
- // possibly crop 'name' in 'name.xx'
- if( nameInfo.first.Length() > cchMaxNamePart )
- {
- nameInfo.first.Set(nameInfo.first.Ptr(), cchMaxNamePart);
- }
- // working display name buffer
- HBufC* pDisplayName = HBufC::NewMaxL(nameInfo.first.Length() + k_cchSuffix);
- AUTO_PUSH_POP_DEL(pDisplayName);
- TPtr ptrDisplayName = pDisplayName->Des();
-
- // potential name to be displayed to user
- ptrDisplayName.Copy(nameInfo.first);
- // full path to go out
- pPathOut = new (ELeave) TFileName;
- AUTO_PUSH_POP(pPathOut);
- bool bFound = false;
- for(TInt idx = 0; idx < k_maxTries; ++idx)
- {
- // re-form path and see if it is unique
- pPathOut->Copy(basePath);
- AppendPath(*pPathOut, ptrDisplayName, CHXAvFile::ntUnspecified);
- pPathOut->Append(nameInfo.second);
-
- DPRINTF(SYMP_FILE, ("AllocUniqueDefaultFilenameL(): testing '%s'n", dbg::CharPtr(*pPathOut)()));
- if(!PathExists(*pPathOut))
- {
- // found a unique name
- bFound = true;
- break;
- }
- // from now on we'll be adding suffix...
- // max chars for 'name' in 'name(NN).xx'
- TInt cchMaxNamePartMinusSuffix = cchMaxNamePart - k_cchSuffix;
- if(cchMaxNamePartMinusSuffix <= 0 )
- {
- // give up...
- break;
- }
- // possibly crop 'name' in 'name(NN)'
- if( nameInfo.first.Length() > cchMaxNamePartMinusSuffix )
- {
- nameInfo.first.Set(nameInfo.first.Ptr(), cchMaxNamePartMinusSuffix);
- }
- // name was not unique; try next (start with 01)
- ptrDisplayName.Format(KDuplicateNameFormat, &nameInfo.first, idx + 1);
- }
- if( !bFound )
- {
- HX_DELETE(pPathOut);
- }
- }
- return pPathOut;
- }
- ////////////////////////////////////////////////////////////
- //
- // fullPath - full path to file or folder; folders must have folder suffix
- //
- bool PathExists(const TDesC& fullPath)
- {
- DPRINTF(SYMP_FILE, ("PathExists(): checking path '%s'n", dbg::CharPtr(fullPath)()));
- RFs& fs = CCoeEnv::Static()->FsSession();
-
- //
- // note: BaflUtils::PathExists() is only api that appears to correctly
- // validate a root folder, e.g., 'c:')
- //
- if(HasFolderSuffix(fullPath))
- {
- return BaflUtils::PathExists(fs, fullPath);
- }
- return BaflUtils::FileExists(fs, fullPath);
-
- }
- ////////////////////////////////
- //
- // return 0-based index of drive relative to 'a'; -1 if no drive specified
- //
- // (note: a valid index maps to TDriveNumer)
- //
- // 'c:' -> 2
- // 'a:' -> 0
- // 'e:foobar -> 4
- // 'foobar' -> -1
- // 'c:hello' -> -1
- //
- TInt GetDriveIndex(const TDesC& path)
- {
- DPRINTF(SYMP_FILE, ("GetDriveIndex(): checking '%s'n", dbg::CharPtr(path)()));
- TInt idx = -1;
- const TInt k_cchMinPath = 2; // must have at least 'a:'
- TInt cchPath = path.Length();
- if( cchPath >= k_cchMinPath )
- {
- TChar ch = path[0];
- bool bGood = ( ch.IsAlpha() && (path[1] == KDriveDelimiter) );
- if( bGood && (cchPath != k_cchMinPath) )
- {
- // a '' is required unless the path is solely in the format 'a:'
- bGood = (path[2] == KPathDelimiter);
- }
- if( bGood )
- {
- ch.LowerCase();
- idx = ch - TChar('a');
- }
- }
- DPRINTF(SYMP_FILE, ("GetDriveIndex(): index is %dn", idx));
- return idx;
- }
- ////////////////////////////////////////////////////
- //
- CHXAvFile::DriveState TranslateDriveErrorCode(TInt err)
- {
- CHXAvFile::DriveState driveState(dsUnknown);
-
- DPRINTF(SYMP_FILE, ("TranslateDriveErrorCode(): epoc code = %dn", err));
- // translate error code
- switch (err)
- {
- case KErrNone:
- driveState = dsAccessible;
- break;
- case KErrLocked:
- driveState = dsLocked;
- break;
- case KErrCorrupt:
- driveState = dsCorrupted;
- break;
- default:
- driveState = dsUnknown;
- break;
- }
- DPRINTF(SYMP_FILE, ("TranslateDriveErrorCode(): code = %dn", driveState));
- return driveState;
- }
- ////////////////////////////////////////////////////
- //
- // lazy-mount drive (if necessary) and return true if locked
- //
- bool IsMountLocked(TInt idxDrive)
- {
- DPRINTF(SYMP_FILE, ("IsMountLocked(): idxDrive = %dn", idxDrive));
- RFs& fs = CCoeEnv::Static()->FsSession();
- TFullName fsName;
- TInt err = fs.FileSystemName(fsName, idxDrive);
- DPRINTF(SYMP_FILE, ("IsMountLocked(): err = %d; fs name = %sn", err, dbg::CharPtr(fsName)()));
- if( (KErrNone == err) && (0 == fsName.Length()) )
- {
- DPRINTF(SYMP_FILE, ("IsMountLocked(): no name; mountingn"));
- //
- // drive is present but not mounted; attempt to mount drive
- // now; mmc mount will succeed if password is cached
- //
- _LIT( KFat, "Fat" );
- err = fs.MountFileSystem(KFat, idxDrive);
- }
-
- return (err == KErrLocked);
- }
- ////////////////////////////////////////////////////
- // from experimentation on device:
- //
- // local fs:
- // FileSystemName returns 0; name = 'Lffs'
- // type = 6 (EMediaFlash); drive attr = 145; media_attr = 4(KMediaAttFormattable)
- //
- // unlocked mmc inserted:
- // FileSystemName returns 0; name = 'Fat'
- // type = 3 (EMediaHardDisk); drive attr = 33; media attr = 84(KMediaAttFormattable + 0x80)
- //
- // unlocked mmc, low mem:
- // type = 0 (EMediaNotPresent); attr = 33; media att = 112 (0x20 = KMediaAttLocked)
- //
- // locked mmc inserted:
- // FileSystemName returns 0; name = ''
- // MountFileSystem returns -22 (KErrLocked)
- // Volume() fails, returns -18 (KErrNotReady)
- //
- // mmc not inserted
- // FileSystemName returns 0; name = 'Fat'
- // Volume() fails, returns -18 (KErrNotReady)
- //
- ////////////////////////////////////////////////////
- // get drive information from drive index
- //
- DriveInfo GetDriveInfo(TInt idxDrive)
- {
- DPRINTF(SYMP_FILE, ("GetDriveInfo(): looking at drive '%c:'n", idxDrive + 'a'));
- DriveInfo info;
-
- if(idxDrive != -1)
- {
- info.idxDrive = idxDrive;
-
- //
- // This will fail if drive is locked or not inserted
- //
- RFs& fs = CCoeEnv::Static()->FsSession();
- TInt err = fs.Volume(info.volInfo, idxDrive);
- if( KErrNone == err )
- {
- info.bVolInfoValid = true;
-
- TDriveInfo& drive = info.volInfo.iDrive;
- DPRINTF(SYMP_FILE, ("GetDriveInfo(): type = %d; drive_attr = %d; media_attr = %dn",
- drive.iType, drive.iDriveAtt, drive.iMediaAtt));
- info.type = drive.iType;
- if(drive.iDriveAtt != EMediaNotPresent)
- {
- // only in this case can we access...
- info.state = dsAccessible;
- }
- else
- {
- // this case (not normal) appears to occur when memory is low!
- DPRINTF(SYMP_FILE, ("GetDriveInfo(): drive absentn"));
- info.state = dsUnknown;
- info.type = EMediaNotPresent; // just for sanity
- }
- if( drive.iMediaAtt & KMediaAttLocked)
- {
- // drive is reported locked when it is not when memory is low; we won't argue
- info.state = dsLocked;
- }
- }
- else
- {
- DPRINTF(SYMP_FILE, ("GetDriveInfo(): Volume() failedn"));
- //
- // Volume() doesn't fail with KErrLocked as you might expect (when drive is in fact locked)! Do explicit check.
- //
- if( IsMountLocked(idxDrive) )
- {
- info.state = dsLocked;
- }
- else
- {
-
- info.state = TranslateDriveErrorCode(err);
- }
- }
- }
- return info;
- }
- ////////////////////////////////////////////////////////////
- // allocate a TFileName with assembled folder and name:
- //
- // first - folder suffix '/' is optional; KNullDesC is OK
- // second - folder prefix '/' is optional; KNullDesC is OK
- // type - if ntFolder, ensure trailing folder suffix '/'
- // - if ntFile, ensure no trailing folder suffix
- // - if ntUnspecified, append second as is
- //
- // examples (before possibly adding or removing trailing folder suffix based on type):
- //
- // "path" + "file" -> "pathfile"
- // "path" + "file' -> "pathfile"
- // "" + "file" -> "file"
- // "c:path" + "" -> "c:path"
- // "path" + "file" -> "pathfile"
- //
- //
- TFileName* AllocFileNameL(const TDesC& first, const TDesC& second, NameType type)
- {
- TFileName* pName = new (ELeave) TFileName;
- AUTO_PUSH_POP(pName);
- pName->Copy(first);
- AppendPath(*pName, second, type);
- return pName;
- }
- TFileName* AllocFileNameL(const TDesC& path, NameType type )
- {
- return AllocFileNameL(path, KNullDesC, type);
- }
- HBufC* AllocFileUrlL(const TDesC& path)
- {
- // get path with backslashes converted to forward slashes
- HBufC* pbuff = CHXAvStringUtils::AllocTextL(path);
- AUTO_PUSH_POP_DEL(pbuff);
- TPtr ptr = pbuff->Des();
- BackToForwardSlash(ptr);
- // in case path has special characters that need to be escaped (e.g., '#' or '%')
- CHXAvEscapedString escPath;
- escPath.EscapePathStr(CHXAvStringUtils::DescToString(*pbuff));
- CHXString strEscaped = escPath.GetEscapedStr();
- HBufC* pEscaped = CHXAvStringUtils::StringToHBuf(strEscaped);
- AUTO_PUSH_POP_DEL(pEscaped);
- // concatenate file:// prefix
- HBufC* pURL = CHXAvStringUtils::AllocTextL(KFileProtocolPrefix, *pEscaped);
-
- return pURL;
- }
- ////////////////////////////////////////////////////////////
- //
- // append path element to path, ensuring that optional path
- // separators make sense
- //
- // path - folder suffix ('/') at end is optional
- // tail - path prefix ('/') at beggining is optional; will be added if missing
- //
- // type - if 'folder' ensures trailing '/' exists on end of path
- // - if 'file' ensures trailing '/' does not exist on end of path
- // - if 'unspecified', just appends tail as is
- void AppendPath(TDes& path, const TDesC& name, NameType type)
- {
- // XXXLCM check total size doesn't overflow KMaxFileName (AppendPathL, or copy to max)
- if( name.Length() > 0 )
- {
- // make sure existing path has trailing folder suffix
- EnsureFolderSuffix(path);
- TPtrC ptrName;
- TInt idxBegin = 0;
- TInt idxEnd = name.Length();
- if( (ntFile == type) && HasFolderSuffix(name) )
- {
- // don't include trailing slash - we are forming a filename
- idxEnd--;
- }
- if(HasFolderPrefix(name))
- {
- // don't append the first path sep
- idxBegin++;
- }
-
- ptrName.Set(name.Mid(idxBegin, idxEnd - idxBegin));
- path.Append(ptrName);
- }
- if( ntFolder == type )
- {
- EnsureFolderSuffix(path);
- }
- }
- ////////////////////////////////////////////////////////////
- //
- // return path with filename part lopped off
- //
- // "foobar" -> foo <-- bar is interpreted as file
- // "foobar" -> foobar
- // "foo" -> foo
- // "file.rm" ->
- // "foo" -> KNullDesc
- // "" -> KNullDesc
- //
- TPtrC GetFolderPath(const TDesC& path)
- {
- TInt idx = path.Length();
- if( idx > 0 )
- {
- // find current folder root
- idx = path.LocateReverse(KPathDelimiter);
- if( KErrNotFound != idx )
- {
- // include trailing ''
- return path.Left(idx + 1);
- }
- }
- return TPtrC(KNullDesC);
- }
- ////////////////////////////////////////////////////////////
- //
- // return path to folder that is parent of current
- // folder
- //
- // "foobar" -> foo <-- bar is interpreted as file
- // "foobar" -> foo
- // "foo" ->
- // "" -> KNullDesc
- // "foo" -> KNullDesc
- // "" -> KNullDesc
- //
- TPtrC GetParentFolder(const TDesC& path)
- {
- TPtrC parent(KNullDesC);
- // find current folder root
- TInt idx = path.LocateReverse(KPathDelimiter);
- if( idx > 0 )
- {
- if( HasFolderSuffix(path) )
- {
- // path name is a folder; skip the folder suffix and get parent folder
- TPtrC current = path.Left(idx);
- idx = current.LocateReverse(KPathDelimiter);
- }
- if( idx > 0 )
- {
- parent.Set(path.Left(idx + 1));
- }
- }
-
- return parent;
- }
- ////////////////////////////////////
- // return true if 'childPath' specifies a path that
- // is under the parentPath
- //
- // c:myfoldermusic c:myfoldermusicrock true
- // c:myfoldermusic c:myfoldermusicstyx.rm true
- // myfoldermusic myfoldermusicclassical true
- // c:myfoldermusic myfoldermusicrock false (ambiguous)
- // c:myfoldermusic c:myfoldermusic false (same path)
- // {empty path} {whatever} false (an invalid path can't have children)
- //
- bool IsSubPath(const TDesC& parentPath, const TDesC& childPath)
- {
- bool bIsSubPath = false;
- TInt parentLength = parentPath.Length();
- // empty parent path means no path (can't have child)
- if( parentLength > 0 )
- {
- // a child path must be longer than the parent path
- if(childPath.Length() > parentPath.Length())
- {
- // get possible matching base path from the parent
- TPtrC childBasePath = childPath.Left(parentLength);
- bIsSubPath = (0 == childBasePath.CompareF(parentPath));
- }
- }
- return bIsSubPath;
- }
- ////////////////////////////////////
- //
- // get name-only part of most-significant part of path
- //
- // "foobarfile.rm" -> "file.rm"
- // "foobar" -> "bar"
- // "foobar" -> "bar"
- // "foobar " -> " "
- // "bar" -> "bar"
- // "bar" -> "bar"
- // "" -> ""
- //
- // other stuff (e.g., "\\") undefined
- //
- TPtrC GetNakedPathNode(const TDesC& path)
- {
- TPtrC name(path);
- TInt idxLastPathSep = path.LocateReverse(KPathDelimiter);
- if( KErrNotFound != idxLastPathSep )
- {
- HX_ASSERT(path.Length() > 0);
- if( idxLastPathSep == path.Length() - 1)
- {
- // node is a folder
- // make path look like a file and recurse
- TPtrC newPath = path.Left(path.Length() - 1);
- name.Set(GetNakedPathNode(newPath));
- }
- else
- {
- // node is a file
- name.Set(path.Mid(idxLastPathSep + 1));
- }
- }
- return name;
- }
- ////////////////////////////////////
- // same as GetNakedPathNode(), but
- // also trims of off file extension
- //
- // "folder/foo.rm" -> "foo"
- // "folder/child/" -> "child"
- // "folder/child.rm/ -> "child" <- oops?
- //
- TPtrC GetNakedName(const TDesC& path)
- {
- TPtrC ptrName = GetNakedPathNode(path);
- TInt idx = ptrName.LocateReverse(KExtDelimiter);
- if( KErrNotFound != idx )
- {
- ptrName.Set(ptrName.Ptr(), idx);
- }
- return ptrName;
- }
- /////////////////////////////////////
- // get extension only (with dot)
- //
- // "folder/foo.rm" -> ".rm"
- //
- TPtrC GetExtension(const TDesC& path)
- {
- TPtrC ptrExt = GetNakedPathNode(path);
- TInt idx = ptrExt.LocateReverse(KExtDelimiter);
- if(KErrNotFound != idx)
- {
- ptrExt.Set(ptrExt.Mid(idx));
- }
- else
- {
- ptrExt.Set(KNullDesC);
- }
- return ptrExt;
- }
- /////////////////////////////////////
- // Trim folder suffix if present and return path
- //
- // c:myfoldermusic => c:myfoldermusic
- // myfolder => myfolder
- // c:myfolderfile.rm => c:myfolderfile.rm
- //
- TPtrC GetEnsureNoFolderSuffix(const TDesC& path)
- {
- TPtrC name(path);
- if( HasFolderSuffix(path) )
- {
- name.Set(path.Left(path.Length() - 1));
- }
- return name;
- }
- ////////////////////////////////////////////////////////////
- // make sure we have enough disk space to make the copy
- //
- // copy goes to flash or mmc
- //
- TInt CheckDiskSpaceForCopyL(const TDesC& fullPathSource, TInt idxDriveDest)
- {
- CCoeEnv* pEnv = CCoeEnv::Static();
- RFs& fs = pEnv->FsSession();
- TEntry entry;
- TInt err = fs.Entry(fullPathSource, entry);
- if( KErrNone == err )
- {
- if( EDriveE == idxDriveDest )
- {
- // assume drive E is mmc
- if( SysUtil::MMCSpaceBelowCriticalLevelL( &fs, entry.iSize) )
- {
- err = KErrDiskFull;
- }
- }
- else
- {
- // assume everything else is flash
- if( SysUtil::FFSSpaceBelowCriticalLevelL( &fs, entry.iSize) )
- {
- err = KErrDiskFull;
- }
- }
- }
- return err;
- }
- ////////////////////////////////////////////////////
- // create list of folders under the parent path
- //
- // useful for populating a folder list (e.g., 'move to', 'save to')
- //
- CDesCArrayFlat* AllocFolderListL(const TDesC& parentPath, bool bSorted)
- {
- CDesCArrayFlat* pItems = new (ELeave) CDesCArrayFlat(20 /*granularity*/);
- AUTO_PUSH_POP(pItems); // out
- // read directory contents under parent path path...
- CHXAvDirectoryReader reader;
- if( reader.SetToPath(parentPath) )
- {
- const CDir* pFolders = reader.GetDirs();
- if( pFolders )
- {
- TInt count = pFolders->Count();
- for( TInt idx = 0; idx < count; ++idx )
- {
- const TEntry& entry = (*pFolders)[idx];
- HX_ASSERT(entry.IsDir());
- if( !CHXAvUtil::ShouldHideFromUser(entry) )
- {
- // add this folder
- pItems->AppendL(entry.iName);
- }
- }
- }
- // just in case; underlying api should sort directory list
- if( bSorted )
- {
- pItems->Sort(ECmpCollated);
- }
- }
- else
- {
- HXSYM_LEAVE(reader.GetLastError());
- }
-
- return pItems;
- }
- ////////////////////////////////////////
- // additional filename validity checking beyond just checking
- // for illegal characters
- //
- // name - filename-only part of path (i.e., not a path)
- //
- FileNameValidity GetFileNameValidity(const TDesC& name)
- {
- FileNameValidity validity = nvValid;
- //
- // check special cases first; RFs::IsValidName() doesn't catch everything
- //
- if(name.Length() > KMaxFileName )
- {
- // name is too long for sure (RFs::IsValidName() will simply return 'false')
- validity = nvTooLong;
- }
- else if(0 == name.Right(1).Compare(CHXAvUtil::KDot) )
- {
- // name can never end in dot
- validity = nvInvalidDots;
- }
- else if(0 == name.Compare(CHXAvUtil::KDot) || 0 == name.Compare(CHXAvUtil::KDoubleDot))
- {
- // name cannot be '.' or '..'
- validity = nvInvalidDots;
- }
- else
- {
- RFs& fs = CCoeEnv::Static()->FsSession();
- if(!fs.IsValidName(name))
- {
- validity = nvInvalidIllegalChars;
- }
- }
- return validity;
- }
- ////////////////////////////////////////////////////////////
- // return file size in bytes (-1 if can't determine)
- TInt GetFileSize(const TDesC& fileName)
- {
- CCoeEnv* pEnv = CCoeEnv::Static();
- RFs& fs = pEnv->FsSession();
- TEntry entry;
- TInt err = fs.Entry(fileName, entry);
- if(KErrNone != err)
- {
- entry.iSize = -1;
- }
- return entry.iSize;
- }
- // Unset read-only attribute for file (not folder)
- TInt EnsureClearReadOnlyAttributeForFile(const TDesC& fileName)
- {
- HX_ASSERT(!HasFolderSuffix(fileName));
- CCoeEnv* pEnv = CCoeEnv::Static();
- RFs& fs = pEnv->FsSession();
- //KEntryAttVolume
- //KEntryAttDir
- //KEntryAttArchive
- //KEntryAttSystem
- //KEntryAttHidden
- //KEntryAttReadOnly
- //KEntryAttNormal
- TUint attr = 0;
- TInt err = fs.Att(fileName, attr);
- if( KErrNone == err )
- {
- //DPRINTF(SYMP_FILE, ("EnsureClearReadOnlyAttributeForFile(): att for '%s' = 0x%08xn", dbg::CharPtr(fileName)(), attr));
- if( attr & KEntryAttReadOnly )
- {
- DPRINTF(SYMP_FILE, ("EnsureClearReadOnlyAttributeForFile(): unsetting read-only attributen"));
- err = fs.SetAtt(fileName, 0, KEntryAttReadOnly /*remove*/);
- }
- }
- return err;
- }
- //
- // Unset read-only attribute for given file. If fileName is a folder (indicated
- // by trailing slash), all folder children will have read-only attributes removed.
- //
- TInt EnsureClearReadOnlyAttributeL(const TDesC& fileName)
- {
- RFs& fs = CCoeEnv::Static()->FsSession();
- TInt err = KErrNone;
- if( HasFolderSuffix(fileName) )
- {
- DPRINTF(SYMP_FILE, ("EnsureClearReadOnlyAttributeL(): unsetting read-only attribute for foldern"));
- // recursively unset attributes for folder
- CFileMan* pFileMan = CFileMan::NewL(fs);
- AUTO_PUSH_POP_DEL(pFileMan);
-
- TTime tm; // ignored
- const TUint setMask = 0;
- const TUint clearMask = KEntryAttReadOnly;
- // trim folder suffix
- TPtrC ptrName = CHXAvFile::GetEnsureNoFolderSuffix(fileName);
- // note: this does not work well for filenames (even with flag set 0)?!? (in emulator file becomes inaccessible)
- err = pFileMan->Attribs(ptrName, setMask, clearMask, tm, CFileMan::ERecurse);
- }
- else
- {
- err = EnsureClearReadOnlyAttributeForFile(fileName);
- }
- DPRINTF(SYMP_FILE, ("EnsureClearReadOnlyAttributeL(): result = %dn", err));
- return err;
- }
- ////////////////////////////////////////////////
- // return 'true' if path is absolute, i.e., begins with:
- //
- // a) a drive letter colon and slash (c:)
- // b) a slash ()
- //
- bool HasDriveOrRootPrefix(const TDesC& path)
- {
- bool bHasIt = false;
- TInt idx = GetDriveIndex(path);
- if( idx != -1 )
- {
- bHasIt = false;
- }
- else
- {
- bHasIt = HasFolderPrefix(path);
- }
- return bHasIt;
- }
- ////////////////////////////////////////////////
- // prefix given relative path with full player app folder path
- //
- TFileName* AllocAppFolderPathL(const TDesC& path)
- {
- // also see:
- // #include <aknutils.h>
- // CompleteWithAppPath(fullPathLibRoot);
- HX_ASSERT(!HasDriveOrRootPrefix(path));
- TFileName* pOut = new (ELeave) TFileName;
- AUTO_PUSH_POP(pOut);
- // get our app directory base path
- CEikAppUi* pAppUI = reinterpret_cast<CEikAppUi*>(CCoeEnv::Static()->AppUi());
- HX_ASSERT(pAppUI);
- TFileName dllName = pAppUI->Application()->DllName();
- TPtrC appRootPath = GetFolderPath(dllName);
- pOut->Copy(appRootPath);
- AppendPath(*pOut, path, CHXAvFile::ntUnspecified);
-
- return pOut;
- }
- ////////////////////////////////////////////////////////
- // Allocate path from preferences. If path is not fully
- // specified (with drive letter), assume it is relative
- // to app folder
- //
- // return 0 if pref key does not exist
- //
- TFileName* AllocFullPrefPathL(IHXPreferences* pPrefs, const char* prefKey)
- {
- TFileName* pFullPath = 0;
-
- // get path from prefs
- CHXString strPath = prefs::GetString(pPrefs, prefKey);
- if(!strPath.IsEmpty())
- {
- CHXAvCleanString descPath(strPath);
- if(!CHXAvFile::HasDriveOrRootPrefix(descPath()))
- {
- pFullPath = CHXAvFile::AllocAppFolderPathL(descPath());
- }
- else
- {
- pFullPath = new (ELeave) TFileName();
- HXSYM_LEAVE_IF_FALSE(descPath().Length() <= KMaxFileName);
- pFullPath->Copy(descPath());
- }
- }
- return pFullPath;
- }
- } //ns CHXAvFile