33 #include <sys/types.h>
41 #include <sys/param.h>
43 #if defined(__APPLE__)
44 #include <CoreFoundation/CFString.h>
48 #define PATH_DELIMITER '\\'
49 #define f_fopen _wfopen
50 #define f_remove _wremove
51 #define f_rename _wrename
53 #define f_statbuf struct _stat
55 #define PATH_DELIMITER '/'
57 #define f_remove remove
58 #define f_rename rename
60 #define f_statbuf struct stat
63 #if !defined(_WIN32) && !defined(__APPLE__)
81 std::string charset(
"C");
82 char *env_lang = getenv(
"LANG");
83 if(env_lang && charset.compare(env_lang) != 0)
86 size_t locale_start = charset.rfind(
".");
87 if(locale_start != std::string::npos)
88 charset = charset.substr(locale_start+1);
92 if((charset.compare(
"UTF-8") == 0) || (charset.compare(
"utf-8") == 0))
95 iconv_t ic_descr = iconv_t(-1);
98 ic_descr = to_UTF ? iconv_open(
"UTF-8", charset.c_str()) : iconv_open(charset.c_str(),
"UTF-8");
100 catch(std::exception &) {}
102 if(ic_descr == iconv_t(-1))
105 char* inptr = (
char*)str_in.c_str();
106 size_t inleft = str_in.size();
116 outptr = (
char *)outbuf;
117 outleft =
sizeof(outbuf) -
sizeof(outbuf[0]);
119 size_t result = iconv(ic_descr, &inptr, &inleft, &outptr, &outleft);
120 if(result ==
size_t(-1))
128 iconv_close(ic_descr);
136 iconv_close(ic_descr);
148 wchar_t *path = _wgetcwd( 0, 0 );
150 char *path = getcwd( 0, 0 );
154 ret = decodeName( path );
161 f_string _varname = encodeName( varname );
163 if(
wchar_t *var = _wgetenv( _varname.c_str() ) )
165 if(
char *var = getenv( _varname.c_str() ) )
167 return decodeName( var );
168 return std::string();
180 return std::wstring();
181 int len = MultiByteToWideChar(CP_UTF8, 0, fileName.data(),
int(fileName.size()), 0, 0);
182 std::wstring out(len, 0);
183 len = MultiByteToWideChar(CP_UTF8, 0, fileName.data(),
int(fileName.size()), &out[0], len);
186 #elif defined(__APPLE__)
190 return std::string();
191 CFMutableStringRef ref = CFStringCreateMutable(0, 0);
192 CFStringAppendCString(ref, fileName.c_str(), kCFStringEncodingUTF8);
193 CFStringNormalize(ref, kCFStringNormalizationFormD);
195 char *composed =
new char[fileName.size() * 2];
196 CFStringGetCString(ref, composed, fileName.size() * 2, kCFStringEncodingUTF8);
199 std::string out(composed);
206 {
return convertUTF8(fileName,
false); }
217 if(localFileName.empty())
218 return std::string();
219 int len = WideCharToMultiByte(CP_UTF8, 0, localFileName.data(),
int(localFileName.size()), 0, 0, 0, 0);
220 std::string out(len, 0);
221 len = WideCharToMultiByte(CP_UTF8, 0, localFileName.data(),
int(localFileName.size()), &out[0], len, 0, 0);
224 #elif defined(__APPLE__)
227 if(localFileName.empty())
228 return std::string();
229 CFMutableStringRef ref = CFStringCreateMutable(0, 0);
230 CFStringAppendCString(ref, localFileName.c_str(), kCFStringEncodingUTF8);
231 CFStringNormalize(ref, kCFStringNormalizationFormC);
233 char *composed =
new char[localFileName.size() * 2];
234 CFStringGetCString(ref, composed, localFileName.size() * 2, kCFStringEncodingUTF8);
237 std::string out(composed);
244 {
return convertUTF8(localFileName,
true); }
257 if(
f_stat(_path.c_str(), &fileInfo) != 0)
261 if((fileInfo.st_mode & S_IFMT) == S_IFDIR)
278 if(!_path.empty() && (_path[_path.size() - 1] == L
'/' || _path[_path.size() - 1] == L
'\\'))
279 _path = _path.substr(0, _path.size() - 1);
285 if(
f_stat(_path.c_str(), &fileInfo) != 0)
288 if((fileInfo.st_mode & S_IFMT) != S_IFDIR)
304 f_stat(_path.c_str(), &fileInfo);
305 return gmtime(&fileInfo.st_mtime);
316 size_t pos = path.find_last_of(
"/\\");
317 return pos == std::string::npos ? path : path.substr(pos + 1);
330 return pos == std::string::npos ?
"" : path.substr(0, pos);
345 std::string dir(directory);
346 if(!dir.empty() && (dir[dir.size() - 1] ==
'/' || dir[dir.size() - 1] ==
'\\'))
348 dir = dir.substr(0, dir.size() - 1);
354 std::replace(path.begin(), path.end(),
'\\',
'/');
358 #ifdef _POSIX_VERSION
359 std::replace(path.begin(), path.end(),
'\\',
'/');
361 std::replace(path.begin(), path.end(),
'/',
'\\');
375 wchar_t *fileName = _wtempnam(0, 0);
379 char *fileName = tempnam(0, 0);
383 std::string path = decodeName(fileName);
385 tempFiles.push(path);
411 if(directoryExists(path))
416 std::string parentDir(path);
417 if(parentDir[parentDir.size() - 1] ==
'/' || parentDir[parentDir.size() - 1] ==
'\\')
419 parentDir = parentDir.substr(0, parentDir.size() - 1);
421 parentDir = parentDir.substr(0, parentDir.find_last_of(
"/\\"));
423 if(!directoryExists(parentDir))
425 createDirectory(parentDir);
430 int result = _wmkdir(_path.c_str());
432 DEBUG(
"Creating directory '%s' failed with errno = %d", _path.c_str(), errno);
434 DEBUG(
"Created directory '%s'", _path.c_str());
437 int result = mkdir(_path.c_str(), 0700);
438 DEBUG(
"Created directory '%s' with result = %d", _path.c_str(), result);
441 if(result || !directoryExists(path))
456 std::string directory = tempDirectory();
457 createDirectory(directory);
472 if(
f_stat(_path.c_str(), &fileInfo) != 0)
475 if((fileInfo.st_mode & S_IFMT) == S_IFDIR)
478 if (fileInfo.st_size < 0)
481 return static_cast<unsigned long>(fileInfo.st_size);
492 if( _path.length() == 0 )
return true;
493 if( _path[0] ==
'/' )
return false;
496 if( _path.length() >= 2 &&
497 ((iswalpha(_path[0]) && _path[1] ==
':') ||
498 (_path[0] ==
'/' && _path[1] ==
'/')) )
520 bool listEmptyDirectories,
bool unixStyle)
throw(
IOException)
528 std::vector<std::string> files;
531 std::vector<std::string> subDirectories = getDirSubElements(directory,
true,
false, unixStyle);
532 std::vector<std::string>::const_iterator subDirectory = subDirectories.begin();
533 for ( ; subDirectory != subDirectories.end(); subDirectory++ )
536 std::vector<std::string> list = listFiles(path(directory, *subDirectory), relative, listEmptyDirectories, unixStyle);
540 for(std::vector<std::string>::const_iterator iter = list.begin(); iter != list.end(); iter++)
543 files.push_back(path(*subDirectory, *iter, unixStyle));
545 files.push_back(*iter);
550 if(listEmptyDirectories)
553 files.push_back(std::string(*subDirectory) + pathDelim);
555 files.push_back(path(directory, *subDirectory, unixStyle) + pathDelim);
561 std::vector<std::string> dirFiles = getDirSubElements(directory, relative,
true, unixStyle);
562 files.insert(files.begin(), dirFiles.begin(), dirFiles.end());
578 if(!fileExists(srcPath))
583 if(!overwrite && fileExists(destPath))
585 THROW_IOEXCEPTION(
"Destination file exists '%s' can not copy to there. Overwrite flag is set to false.", destPath.c_str());
589 std::ifstream ifs(encodeName(srcPath).c_str(), std::ios::binary);
590 std::ofstream ofs(encodeName(destPath).c_str(), std::ios::binary | std::ios::trunc);
597 if(ifs.fail() || ofs.fail())
599 THROW_IOEXCEPTION(
"Failed to copy file '%s' to '%s'.", srcPath.c_str(), destPath.c_str());
614 if(!fileExists(srcPath))
619 if(!overwrite && fileExists(destPath))
621 THROW_IOEXCEPTION(
"Destination file exists '%s' can not move to there. Overwrite flag is set to false.", destPath.c_str());
624 f_string _srcPath = encodeName(srcPath);
625 f_string _destPath = encodeName(destPath);
626 int result =
f_rename(_srcPath.c_str(), _destPath.c_str());
630 copyFile( srcPath, destPath, overwrite );
631 result =
f_remove( _srcPath.c_str() );
636 WARN(
"Failed to remove source file '%s' when moving it to '%s'.", _srcPath.c_str(), _destPath.c_str() );
653 bool relative,
bool filesOnly,
bool unixStyle)
throw(
IOException)
655 std::vector<std::string> files;
657 #ifdef _POSIX_VERSION
659 std::string _directory = encodeName(directory);
660 DIR* pDir = opendir(_directory.c_str());
666 char fullPath[MAXPATHLEN];
669 while((entry = readdir(pDir)) != NULL)
671 if(std::string(
".").compare(entry->d_name) == 0
672 || std::string(
"..").compare(entry->d_name) == 0)
677 sprintf(fullPath,
"%s/%s", _directory.c_str(), entry->d_name);
678 lstat(fullPath, &info);
680 if((!filesOnly && (entry->d_type == 0x04||S_ISDIR(info.st_mode)))
681 || (filesOnly && (entry->d_type == 0x08||S_ISREG(info.st_mode))))
684 files.push_back(decodeName(entry->d_name));
686 files.push_back(path(directory, decodeName(entry->d_name), unixStyle));
694 WIN32_FIND_DATAW findFileData;
699 if ( directory.size() > MAX_PATH )
702 THROW_IOEXCEPTION(
"Directory path '%s' exceeds the limit %d", directory.c_str(), MAX_PATH);
705 std::wstring findPattern = encodeName(directory +
"\\*");
706 hFind = ::FindFirstFileW(findPattern.c_str(), &findFileData);
709 THROW_IOEXCEPTION(
"Listing contents of directory '%s' failed with error %d", directory.c_str(), ::GetLastError());
714 std::wstring fileName(findFileData.cFileName);
715 if ( fileName == L
"." || fileName == L
".." )
720 if(!filesOnly && (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
721 || filesOnly && !(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
724 files.push_back(decodeName(fileName));
726 files.push_back(path(directory, decodeName(fileName), unixStyle));
728 }
while ( ::FindNextFileW(hFind, &findFileData) !=
FALSE );
731 if ( ::GetLastError() != ERROR_NO_MORE_FILES )
733 THROW_IOEXCEPTION(
"Listing contents of directory '%s' failed with error %d", directory.c_str(), ::GetLastError());
765 std::string result(fullDirectory);
767 #ifndef _POSIX_VERSION
768 std::replace(result.begin(), result.end(),
'\\',
'/');
771 return digidoc::util::File::toUri(
"file://" + result +
"/" + relativeFilePath);
782 f_string _fname = encodeName(fname);
784 WARN(
"Tried to remove the temporary file or directory '%s', but failed.", _fname.c_str() );
794 f_string _dname = encodeName(dname);
796 if (!RemoveDirectoryW(_dname.c_str()))
798 if (
remove( _dname.c_str() ) != 0)
800 WARN(
"Tried to remove the temporary directory '%s', but failed.", _dname.c_str() );
811 std::vector<std::string> subDirs = getDirSubElements(dname,
false,
false,
false);
812 for (std::vector<std::string>::reverse_iterator it = subDirs.rbegin(); it != subDirs.rend(); it++)
814 removeDirectoryRecursively(*it);
818 std::vector<std::string> subFiles = getDirSubElements(dname,
false,
true,
false);
819 for (std::vector<std::string>::reverse_iterator it = subFiles.rbegin(); it != subFiles.rend(); it++)
821 DEBUG(
"Deleting the temporary file '%s'", it->c_str() );
826 DEBUG(
"Deleting the temporary directory '%s'", dname.c_str() );
827 removeDirectory(dname);
836 while (!tempFiles.empty())
838 if ( directoryExists(tempFiles.top()) )
839 removeDirectoryRecursively(tempFiles.top());
841 removeFile(tempFiles.top());
858 static std::string legal_chars =
"-_.!~*'();/?:@&=+$,";
859 std::ostringstream dst;
860 for(std::string::const_iterator
i = path.begin();
i != path.end(); ++
i)
862 if( ((*
i >= 0x61 && *
i <= 0x7A)
863 || (*
i >= 0x41 && *
i <= 0x5A)
864 || (*
i >= 0x30 && *
i <= 0x39))
865 || legal_chars.find(*
i) != std::string::npos )
868 dst << '%' << std::hex << std::uppercase << (static_cast<int>(*i) & 0xFF);
875 std::ostringstream dst;
876 for(std::string::const_iterator
i = in.begin();
i != in.end(); ++
i)
880 dst <<
'%' << char(toupper( *(
i + 1) )) << char(toupper( *(
i + 2) ));
897 std::ostringstream dst;
898 for(std::string::const_iterator
i = uri.begin();
i != uri.end(); ++
i)
902 const char from[2] = { *(
i + 1), *(
i + 2) };
903 dst << char(strtol( from, 0, 16 ));