namespace sys; default: #define set _set #define uint _uint #define File _File #define strlen _strlen #undef __BLOCKS__ #include #include #include #define UNICODE #define IS_ALUNDER(ch) ((ch) == '_' || isalnum((ch))) #if defined(ECERE_BOOTSTRAP) #undef __WIN32__ #undef __linux__ #undef __APPLE__ #undef __UNIX__ #endif #ifndef ECERE_BOOTSTRAP #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__) #include #include #include #include #endif #if defined(__unix__) || defined(__APPLE__) #include #endif #if defined(__WIN32__) || defined(__WATCOMC__) #include #else #include #endif #if defined(__WIN32__) #define WIN32_LEAN_AND_MEAN #define String String_ #include #undef String #include BOOL WINAPI GetVolumePathName(LPCTSTR lpszFileName,LPTSTR lpszVolumePathName,DWORD cchBufferLength); // Missing function... /* #ifndef WNetGetResourceInformation DWORD APIENTRY WNetGetResourceInformationA(LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD lpcbBuffer, LPTSTR* lplpSystem); #ifdef UNICODE #define WNetGetResourceInformation WNetGetResourceInformationW #else #define WNetGetResourceInformation WNetGetResourceInformationA #endif #endif */ #else #include #endif #include "zlib.h" #endif //#ifndef ECERE_BOOTSTRAP private: #undef set #undef uint #undef File #undef strlen import "System" #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET) && !defined(ECERE_BOOTSTRAP) import "HTTPFile" #endif import "dataTypes" // IMPLEMENTATION OF THESE IS IN _File.c default: FILE *eC_stdin(void); FILE *eC_stdout(void); uint FILE_GetSize(FILE * input); bool FILE_Lock(FILE * input, FILE * output, FileLock type, uint64 start, uint64 length, bool wait); void FILE_set_buffered(FILE * input, FILE * output, bool value); FileAttribs FILE_FileExists(char * fileName); bool FILE_FileGetSize(char * fileName, FileSize * size); bool FILE_FileGetStats(char * fileName, FileStats stats); void FILE_FileFixCase(char * file); void FILE_FileOpen(char * fileName, FileOpenMode mode, FILE ** input, FILE **output); private: FileSystem httpFileSystem; public class FileSize : uint { // defaultAlignment = Right; /* void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, int alignment, DataDisplayFlags displayFlags) { char string[16]; int len; eUtils_PrintSize(string, *size, 2); len = strlen(string); surface.WriteTextDots(alignment, x, y, width, string, len); } */ int OnCompare(FileSize data2) { int result = 0; if(&this && &data2) { if(this > data2) result = 1; else if(this < data2) result = -1; } return result; } char * OnGetString(char * string, void * fieldData, bool * needClass) { PrintSize(string, this, 2); return string; } bool OnGetDataFromString(char * string) { char * end; double value = strtod(string, &end); uint multiplier = 1; if(strstr(end, "GB") || strstr(end, "gb")) multiplier = (uint)1024 * 1024 * 1024; else if(strstr(end, "MB") || strstr(end, "mb")) multiplier = (uint)1024 * 1024; else if(strstr(end, "KB") || strstr(end, "kb")) multiplier = 1024; this = (uint)(multiplier * value); return true; } }; public class FileSize64 : uint64 { int OnCompare(FileSize64 data2) { int result = 0; if(&this && &data2) { if(this > data2) result = 1; else if(this < data2) result = -1; } return result; } char * OnGetString(char * string, void * fieldData, bool * needClass) { PrintBigSize(string, this, 2); return string; } bool OnGetDataFromString(char * string) { char * end; double value = strtod(string, &end); uint64 multiplier = 1; if(strstr(end, "PB") || strstr(end, "pb")) multiplier = (uint64)1024 * 1024 * 1024 * 1024; else if(strstr(end, "TB") || strstr(end, "tb")) multiplier = (uint64)1024 * 1024 * 1024 * 1024; else if(strstr(end, "GB") || strstr(end, "gb")) multiplier = (uint64)1024 * 1024 * 1024; else if(strstr(end, "MB") || strstr(end, "mb")) multiplier = (uint64)1024 * 1024; else if(strstr(end, "KB") || strstr(end, "kb")) multiplier = 1024; this = (uint64)(multiplier * value); return true; } }; class FileSystem { virtual File ::Open(char * archive, char * name, FileOpenMode mode); // Query on names virtual FileAttribs ::Exists(char * archive, char * fileName); virtual bool ::GetSize(char * archive, char * fileName, FileSize * size); virtual bool ::Stats(char * archive, char * fileName, FileStats stats); virtual void ::FixCase(char * archive, char * fileName); // File Listing virtual bool ::Find(FileDesc file, char * archive, char * name); virtual bool ::FindNext(FileDesc file); virtual void ::CloseDir(FileDesc file); // Archive manipulation virtual Archive ::OpenArchive(char * fileName, ArchiveOpenFlags create); virtual bool ::QuerySize(char * fileName, FileSize * size); }; public enum FileOpenMode { read = 1, write, append, readWrite, writeRead, appendRead }; public enum FileSeekMode { start, current, end }; #if !defined(ECERE_BOOTSTRAP) static FileDialog fileDialog { text = $"Select File" }; #endif public enum FileLock { unlocked = 0, // LOCK_UN _SH_DENYNO shared = 1, // LOCK_SH _SH_DENYWR exclusive = 2 // LOCK_EX _SH_DENYRW }; public class File : IOChannel { FILE * input, * output; uint ReadData(byte * bytes, uint numBytes) { return Read(bytes, 1, numBytes); } uint WriteData(byte * bytes, uint numBytes) { return Write(bytes, 1, numBytes); } ~File() { if(output && output != input) { openCount--; fclose(output); } if(input) { openCount--; fclose(input); } input = null; output = null; } bool OnGetDataFromString(char * string) { if(!string[0]) { this = null; return true; } else { File f = FileOpen(string, read); if(f) { this = TempFile { }; while(!f.Eof()) { byte buffer[4096]; uint read = f.Read(buffer, 1, sizeof(buffer)); Write(buffer, 1, read); } delete f; return true; } } return false; } char * OnGetString(char * tempString, void * fieldData, bool * needClass) { if(this) { PrintSize(tempString, GetSize(), 2); return tempString; } return null; } #ifndef ECERE_BOOTSTRAP Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData) { Window editData = class::OnEdit(dataBox, obsolete, x + 24, y, w - 48, h, userData); Button load { dataBox, inactive = true, text = $"Import"."Imp", hotKey = f2, position = { Max(x + 24, x + w - 24), y }, size = { 24, h }; bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods) { fileDialog.master = rootWindow; fileDialog.filePath = ""; fileDialog.type = open; if(fileDialog.Modal() == ok) { char * filePath = fileDialog.filePath; File output = null; if(output.OnGetDataFromString(filePath)) { SetData(output, false); Refresh(); } } return true; } }; Button save { dataBox, inactive = true, text = $"Export"."Exp", hotKey = f2, position = { Max(x + 24, x + w - 48), y }, size = { 24, h }; bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods) { fileDialog.master = rootWindow; fileDialog.type = save; fileDialog.filePath = ""; if(fileDialog.Modal() == ok) { char * filePath = fileDialog.filePath; File f = FileOpen(filePath, write); if(f) { File input = *(void **)data; input.Seek(0, start); while(!input.Eof()) { byte buffer[4096]; uint read = input.Read(buffer, 1, sizeof(buffer)); f.Write(buffer, 1, read); } delete f; } } return true; } }; load.Create(); save.Create(); return editData; } #endif //#ifndef ECERE_BOOTSTRAP #if !defined(ECERE_VANILLA) && !defined(ECERE_NOARCHIVE) && !defined(ECERE_BOOTSTRAP) void OnSerialize(IOChannel channel) { uint size = this ? GetSize() : MAXDWORD; if(this) { byte * uncompressed = new byte[size]; Seek(0, start); if(uncompressed || !size) { uint count = Read(uncompressed, 1, size); if(count == size) { uint cSize = size + size / 1000 + 12; byte * compressed = new byte[cSize]; if(compressed) { compress2(compressed, &cSize, uncompressed, size, 9); size.OnSerialize(channel); cSize.OnSerialize(channel); channel.WriteData(compressed, cSize); delete compressed; } } delete uncompressed; } } else size.OnSerialize(channel); /* byte data[4096]; uint c; size.OnSerialize(channel); // Will add position... if(this) { Seek(0, start); for(c = 0; c 1; } // Strings and numbers separated by spaces, commas, tabs, or CR/LF, handling quotes bool GetString(char * string, int max) { int c; char ch; bool quoted = false; bool result = true; *string = 0; while(true) { if(!Getc(&ch)) result = false; if( (ch!='\n') && (ch!='\r') && (ch!=' ') && (ch!=',') && (ch!='\t')) break; if(Eof()) break; } if(result) { for(c=0; c 0) { file.stats.attribs = FileAttribs { isDirectory = true, isShare = true }; file.stats.size = 0; file.stats.accessed = file.stats.created = file.stats.modified = 0; UTF16toUTF8Buffer(buffer->lpRemoteName, file.path, MAX_LOCATION); GetLastDirectory(file.path, file.name); result = file; d.resources = buffer; d.numResources = count; d.resource = 1; } else delete buffer; } else { int c; nr.lpProvider = L"Microsoft Windows Network"; // Entire Network WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle); while(true) { int returnCode = WNetEnumResource(handle, &count, buffer, &size); if(returnCode != ERROR_MORE_DATA) break; count = 0xFFFFFFFF; buffer = (NETRESOURCE *)renew0 buffer byte[size]; } WNetCloseEnum(handle); for(c = 0; clpRemoteName, file.path, MAX_LOCATION); strlwr(file.path); file.path[2] = (char)toupper(file.path[2]); GetLastDirectory(file.path, file.name); result = file; d.resources = resources; d.numResources = countInGroup; d.resource = 1; d.workGroups = buffer; d.numWorkGroups = count; d.workGroup = c; break; } else delete resources; } if(c >= count && buffer) delete buffer; } } #else struct dirent *de; struct stat s; d.d = opendir((path && path[0]) ? path : "."); if(d.d && (de = readdir(d.d))) { if(path[0]) { strcpy(file.path, path); if(path[1]) strcat(file.path, DIR_SEPS); } strcpy(file.name,de->d_name); strcat(file.path, file.name); if(!stat(file.path, &s)) { file.stats.attribs = (s.st_mode&S_IFDIR) ? FileAttribs { isDirectory = true } : FileAttribs { isFile = true }; file.stats.size = (FileSize)s.st_size; file.stats.accessed = s.st_atime; file.stats.modified = s.st_mtime; file.stats.created = s.st_ctime; } strcpy(d.name, path); result = file; } #endif } if(!result) delete d; } if(!result) delete file; } if(result) { while(result && !result.Validate(extensions)) result = result.FindNext(extensions); } return result; } private class FileDesc : struct { FileStats stats; char name[MAX_FILENAME]; char path[MAX_LOCATION]; subclass(FileSystem) system; Dir dir; bool Validate(char * extensions) { if(strcmp(name, "..") && strcmp(name, ".") && strcmp(name, "")) { if(extensions && !stats.attribs.isDirectory) { char extension[MAX_EXTENSION], compared[MAX_EXTENSION]; int c; GetExtension(name, extension); for(c = 0; extensions[c];) { int len = 0; char ch; for(;(ch = extensions[c]) && !IS_ALUNDER(ch); c++); for(;(ch = extensions[c]) && IS_ALUNDER(ch); c++) compared[len++] = ch; compared[len] = '\0'; if(!strcmpi(extension, compared)) return true; } } else return true; } return false; } FileDesc FindNext(char * extensions) { FileDesc result = null; Dir d = dir; name[0] = '.'; name[1] = '\0'; while(!Validate(extensions)) { result = null; if(system) { if(system.FindNext(this)) result = this; else break; } else { #if defined(__WIN32__) if(!strcmp(d.name, "/")) { int c; uint drives = (uint)d.fHandle; for(c = 0; c<26; c++) { if(drives & (1<d_name); strcpy(path, d.name); if(d.name[0] && d.name[1]) strcat(path, DIR_SEPS); strcat(path, name); if(!stat(path, &s)) { stats.attribs = FileAttribs { }; stats.attribs = (s.st_mode&S_IFDIR) ? FileAttribs { isDirectory = true } : FileAttribs { isFile = true }; stats.size = (FileSize)s.st_size; stats.accessed = s.st_atime; stats.modified = s.st_mtime; stats.created = s.st_ctime; } result = this; } else break; #endif } } if(!result) CloseDir(); return result; } void CloseDir(void) { if(system) system.CloseDir(this); else { Dir d = dir; if(d) { #if defined(__WIN32__) if(d.fHandle && strcmp(d.name, "/")) FindClose(d.fHandle); #else closedir(d.d); #endif delete d; } } delete this; } } public struct FileListing { public: char * directory; char * extensions; bool Find() { bool result = false; if(desc) desc = desc.FindNext(extensions); else desc = FileFind(directory, extensions); if(desc) return true; return false; } void Stop() { if(desc) desc.CloseDir(); desc = null; } property char * name { get { return (char *)(desc ? desc.name : null); } }; property char * path { get { return (char *)(desc ? desc.path : null); } }; property FileStats stats { get { value = desc ? desc.stats : FileStats { }; } }; private: FileDesc desc; }; #endif public File CreateTemporaryFile(char * tempFileName, char * template) { #ifndef ECERE_BOOTSTRAP // quick fix for now File f; #if defined(__unix__) || defined(__APPLE__) char buffer[MAX_FILENAME]; int fd; strcpy(buffer, "/tmp/"); strcat(buffer, template); //strcpy(buffer, template); strcat(buffer, "XXXXXX"); // mktemp(buffer); fd = mkstemp(buffer); strcpy(tempFileName, buffer); f = { }; f.output = f.input = fdopen(fd, "r+"); #else char tempPath[MAX_LOCATION]; GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path GetTempFileNameA(tempPath, template, 0, tempFileName); f = FileOpen(tempFileName, readWrite); #endif return f; #endif } #undef DeleteFile public void CreateTemporaryDir(char * tempFileName, char * template) { #ifndef ECERE_BOOTSTRAP // quick fix for now #if defined(__unix__) || defined(__APPLE__) char buffer[MAX_FILENAME]; strcpy(buffer, "/tmp/"); strcat(buffer, template); //strcpy(buffer, template); strcat(buffer, "XXXXXX"); // mkstemp(buffer); mkdtemp(buffer); strcpy(tempFileName, buffer); #else char tempPath[MAX_LOCATION]; GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path GetTempFileNameA(tempPath, template, 0, tempFileName); DeleteFile(tempFileName); MakeDir(tempFileName); #endif #endif } public void MakeSlashPath(char * p) { FileFixCase(p); #ifdef WIN32 ChangeCh(p, '\\', '/'); #endif } public void MakeSystemPath(char * p) { FileFixCase(p); } public char * CopySystemPath(char * p) { char * d = CopyString(p); if(d) MakeSystemPath(d); return d; } public char * CopyUnixPath(char * p) { char * d = CopyString(p); if(d) MakeSlashPath(d); return d; } public char * GetSystemPathBuffer(char * d, char * p) { if(d != p) strcpy(d, p ? p : ""); MakeSystemPath(d); return d; } public char * GetSlashPathBuffer(char * d, char * p) { if(d != p) strcpy(d, p ? p : ""); MakeSlashPath(d); return d; }