#include "File.h" #include "Key.h" #include "Text.h" #include "Time.h" #ifdef WIN32 # include # include # pragma comment(lib, "Shlwapi.lib") #else # include # include # include #endif using namespace Framework; using namespace Encryption; // Content of the File class from File.h // Constructor File::File() : ReferenceCounter(), stream(0), pfad(0), gr(0), tmpLByte(0), tmpLBPos(7), tmpSByte(0), tmpSBPos(-1), key(0) {} //! Constructor File::File(const char* pfad) : File() { setFile(pfad); } //! Constructor File::File(Text* pfad) : File() { setFile(pfad); } // Destructor File::~File() { if (key) key->release(); if (stream) delete stream; if (pfad) pfad->release(); } // non-constant void File::setFile(const char* pfad) // sets the file { if (istOffen()) close(); if (!this->pfad) this->pfad = new Text(); this->pfad->setText(pfad); gr = 0; } void File::setFile(Text* pfad) { if (istOffen()) close(); if (!this->pfad) this->pfad = new Text(); this->pfad->setText(*pfad); pfad->release(); gr = 0; } bool File::umbenennen(const char* pfad) // renames and possibly moves the file { if (!pfad) return 0; if (FileRename(this->pfad->getText(), pfad)) { this->pfad->setText(pfad); return 1; } return 0; } bool File::umbenennen(Text* pfad) { if (!this->pfad) { pfad->release(); return 0; } if (FileRename(this->pfad->getText(), pfad->getText())) { this->pfad->setText(*pfad); pfad->release(); return 1; } pfad->release(); return 0; } bool File::remove() // deletes the file { if (!pfad) return 0; return FileRemove(dynamic_cast(pfad->getThis())); } bool File::erstellen() // creates the file { if (!pfad) return 0; return FilePathCreate(dynamic_cast(pfad->getThis())); } bool File::open(int style) // opens the file { if (!pfad) return 0; if (stream) delete stream; stream = new std::fstream(); std::ios_base::openmode om = std::ios::binary; if ((style | Style::lesen) == style) om |= std::ios::in; if ((style | Style::schreiben) == style) om |= std::ios::out; stream->open(pfad->getText(), om); if ((style | Style::ende) == style) { if ((style | Style::lesen) == style) stream->seekg(0, std::ios::end); if ((style | Style::schreiben) == style) stream->seekp(0, std::ios::end); } if (!stream->is_open() || !stream->good()) { delete stream; stream = 0; return 0; } tmpLBPos = 7; tmpSBPos = -1; return 1; } void File::setLPosition(__int64 pos, bool ende) // sets the read position { if (!pfad) return; if (stream) { if (ende) stream->seekg(pos, std::ios::end); else stream->seekg(pos, std::ios::beg); } tmpLBPos = 7; } void File::setSPosition(__int64 pos, bool ende) // sets the write position { if (!pfad) return; if (stream) { if (ende) stream->seekp(pos, std::ios::end); else stream->seekp(pos, std::ios::beg); } tmpSBPos = -1; } void File::schreibe(const char* bytes, int len) // writes bytes to file { if (!pfad || !stream) return; if (tmpSBPos >= 0) { tmpSBPos = -1; stream->write(&tmpSByte, 1); tmpSByte = 0; } if (key) { key->setPos(getSPosition()); Bytes* n = new Bytes(bytes, len); key->codieren(dynamic_cast(n->getThis())); stream->write(n->getBytes(), len); n->release(); } else stream->write(bytes, len); } void Framework::File::flush() { if (!pfad || !stream) return; stream->flush(); } void File::lese(char* bytes, int len) // reads bytes from file { if (!pfad) return; if (stream) { __int64 tmp = getLPosition(); stream->read(bytes, len); if (key) { key->setPos(tmp); Bytes* n = new Bytes(); n->setBytesZ(bytes, len); key->decodieren(n); } } tmpLBPos = 7; tmpSBPos = -1; } Text* File::leseZeile() // reads a line { if (!pfad || !stream) return 0; if (istEnde()) return 0; Text* ret = new Text(""); __int64 len = getSize(); for (char c = 0; c != '\n' && stream->tellg() < len;) { __int64 tmp = getLPosition(); stream->read(&c, 1); if (key) { key->setPos(tmp); Bytes* n = new Bytes(); n->setBytesZ(&c, 1); key->decodieren(n); } if (c) ret->append(&c, 1); } tmpSBPos = 7; tmpSBPos = -1; return ret; } void File::close() // closes the file { if (!pfad || !stream) return; if (tmpSBPos >= 0) { if (key) { key->setPos(getSPosition()); Bytes* n = new Bytes(&tmpSByte, 1); key->codieren(dynamic_cast(n->getThis())); stream->write(n->getBytes(), 1); n->release(); } else stream->write(&tmpSByte, 1); } stream->close(); delete stream; stream = 0; } #ifdef WIN32 bool File::setLetzteAEnderung( Time* zeit) // sets the modification date of the file { if (!pfad) { zeit->release(); return 0; } HANDLE hFile = CreateFile(pfad->getText(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { zeit->release(); return 0; } FILETIME ftCreate, ftAccess, ftWrite; if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) { CloseHandle(hFile); zeit->release(); return 0; } SYSTEMTIME stUTC, stLocal; stLocal.wMilliseconds = 0; stLocal.wSecond = zeit->zClock()->getSekunde(); stLocal.wMinute = zeit->zClock()->getMinute(); stLocal.wHour = zeit->zClock()->getStunde(); stLocal.wDay = zeit->zDate()->getTag(); stLocal.wMonth = zeit->zDate()->getMonat(); stLocal.wYear = zeit->zDate()->getJahr(); zeit->release(); if (!TzSpecificLocalTimeToSystemTime(NULL, &stLocal, &stUTC)) { CloseHandle(hFile); return 0; } if (!SystemTimeToFileTime(&stUTC, &ftWrite)) { CloseHandle(hFile); return 0; } if (!SetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) { CloseHandle(hFile); return 0; } CloseHandle(hFile); return 1; } #endif bool File::getNextBit(bool& bit) // read file bit by bit { if (!pfad || !stream) return 0; if (tmpLBPos == 7) { tmpLBPos = -1; __int64 tmp = getLPosition(); stream->read(&tmpLByte, 1); if (key) { key->setPos(tmp); Bytes* n = new Bytes(); n->setBytesZ(&tmpLByte, 1); key->decodieren(n); } } tmpLBPos++; bit = (tmpLByte >> (7 - tmpLBPos)) & 1; return 1; } bool File::setNextBit(bool bit) // write file bit by bit { if (!pfad || !stream) return 0; tmpSBPos++; tmpSByte |= (char)(((char)bit << (7 - tmpSBPos)) & (1 << (7 - tmpSBPos))); if (tmpSBPos == 7) { tmpSBPos = -1; if (key) { key->setPos(getSPosition()); Bytes* n = new Bytes(&tmpSByte, 1); key->codieren(dynamic_cast(n->getThis())); stream->write(n->getBytes(), 1); n->release(); } else stream->write(&tmpSByte, 1); tmpSByte = 0; } return 1; } // Sets the encryption key for the file void File::setKey(char* s, int l) { if (l == 0) { key = (Key*)key->release(); return; } if (key) key->setKey(s, l); else key = new Key(s, l); } // constant bool File::istOrdner() const // checks if the file is a directory { if (!pfad) return 0; return FileIsDirectory(dynamic_cast(pfad->getThis())); } bool File::istOffen() const // checks if the file is open { if (!pfad) return 0; if (stream) return stream->is_open() && stream->good(); return 0; } int File::getUnterdateiAnzahl() const // returns the number of sub-files { #ifdef WIN32 if (!pfad) return 0; if (!FileIsDirectory(dynamic_cast(pfad->getThis()))) return 0; int ret = 0; HANDLE fHandle; WIN32_FIND_DATA wfd; Text stxt = pfad->getText(); stxt.ersetzen('/', '\\'); if (stxt.positionVon('\\') == stxt.getLength() - 1) stxt.append("*"); else stxt.append("\\*"); fHandle = FindFirstFile(stxt.getText(), &wfd); FindNextFile(fHandle, &wfd); while (FindNextFile(fHandle, &wfd)) ++ret; FindClose(fHandle); return ret; #else if (!pfad) return 0; if (!FileIsDirectory(dynamic_cast(pfad->getThis()))) return 0; int ret = 0; Text stxt = pfad->getText(); stxt.ersetzen('\\', '/'); if (stxt.positionVon('/') == stxt.getLength() - 1) stxt.remove(stxt.getLength() - 1); DIR* hdir; hdir = opendir(stxt.getText()); for (dirent* entry = readdir(hdir); entry; entry = readdir(hdir)) { if (entry && entry->d_name[0] != '.') ++ret; } closedir(hdir); return ret; #endif } RCArray* File::getFileList() const // returns a list of sub-files { #ifdef WIN32 if (!pfad) return 0; if (!FileIsDirectory(dynamic_cast(pfad->getThis()))) return 0; HANDLE fHandle; WIN32_FIND_DATA wfd; Text stxt = pfad->getText(); stxt.ersetzen('/', '\\'); if (stxt.positionVon('\\') == stxt.getLength() - 1) stxt.append("*"); else stxt.append("\\*"); fHandle = FindFirstFile(stxt.getText(), &wfd); FindNextFile(fHandle, &wfd); RCArray* ret = new RCArray(); int count = 0; while (FindNextFile(fHandle, &wfd)) { Text* txt = new Text(wfd.cFileName); ret->add(txt, count); ++count; } FindClose(fHandle); return ret; #else if (!pfad) return 0; if (!FileIsDirectory(dynamic_cast(pfad->getThis()))) return 0; Text stxt = pfad->getText(); stxt.ersetzen('\\', '/'); if (stxt.positionVon('/') == stxt.getLength() - 1) stxt.remove(stxt.getLength() - 1); DIR* hdir; hdir = opendir(stxt.getText()); if (hdir) { RCArray* ret = new RCArray(); int count = 0; for (dirent* entry = readdir(hdir); entry; entry = readdir(hdir)) { if (entry && entry->d_name[0] != '.') { ret->add(new Text(entry->d_name), count); ++count; } } closedir(hdir); return ret; } return 0; #endif } __int64 File::getSize() const // returns the size of the file { if (!pfad) return 0; if (gr) return gr; if (!stream || !istOffen()) { std::fstream* stream = new std::fstream(); stream->open(pfad->getText(), std::ios::binary | std::ios::in); __int64 tmp = stream->tellg(); stream->seekg(0, std::ios::end); __int64 ret = stream->tellg(); stream->seekg(tmp, std::ios::beg); stream->close(); delete stream; __int64* size = (__int64*)&gr; *size = ret; return ret; } __int64 tmp = stream->tellg(); stream->seekg(0, std::ios::end); __int64 ret = stream->tellg(); stream->seekg(tmp, std::ios::beg); __int64* size = (__int64*)&gr; *size = ret; return ret; } Time* File::getLastChange() const // returns the date of the last modification { if (!pfad) return 0; #ifdef WIN32 HANDLE hFile = CreateFile(pfad->getText(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) return 0; FILETIME ftCreate, ftAccess, ftWrite; SYSTEMTIME stUTC, stLocal; if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite)) { CloseHandle(hFile); return 0; } CloseHandle(hFile); if (!FileTimeToSystemTime(&ftWrite, &stUTC)) return 0; if (!SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal)) return 0; Time* ret = new Time(); ret->setTime(stLocal.wYear, stLocal.wMonth, stLocal.wDay, stLocal.wHour, stLocal.wMinute, stLocal.wSecond); return ret; #else struct stat attrib; if (stat(pfad->getText(), &attrib) != 0) return 0; tm* clock = gmtime(&(attrib.st_mtime)); Time* ret = new Time(); ret->setTime(clock->tm_year + 1900, clock->tm_mon + 1, clock->tm_mday, clock->tm_hour, clock->tm_min, clock->tm_sec); return ret; #endif } bool File::existiert() const // checks if the file exists { if (!pfad) return 0; return FileExists(dynamic_cast(pfad->getThis())); } __int64 File::getLPosition() const // returns the read position { if (!stream) return 0; return stream->tellg(); } __int64 File::getSPosition() const // returns the write position { if (!stream) return 0; return stream->tellp(); } bool File::istEnde() const // checks if the end of file is reached { if (!stream || stream->tellg() < 0) return 1; __int64 i = getSize(); return stream->tellg() >= i; } Text* File::getPfad() const // returns the file path { return pfad ? dynamic_cast(pfad->getThis()) : 0; } Text* File::zPfad() const { return pfad; } // File Functions void Framework::GetFreePfad(Text* zPfad) // Searches for an unused filename { Text txt = zPfad->getText(); for (int i = 0; FileExists(txt); i++) { txt = zPfad->getText(); txt.append(i); } zPfad->setText(txt); } bool Framework::FilePathCreate(Text* pfad) // Creates a file in the path { bool ret = FilePathCreate(pfad->getText()); pfad->release(); return ret; } bool Framework::FileRemove(Text* pfad) // Deletes the specified file { bool ret = FileRemove(pfad->getText()); pfad->release(); return ret; } bool Framework::FileRename( Text* pfad_alt, Text* pfad_neu) // Renames the file { bool ret = FileRename(pfad_alt->getText(), pfad_neu->getText()); pfad_alt->release(); pfad_neu->release(); return ret; } bool Framework::FileExists(Text* pfad) // Checks if the file exists { bool ret = FileExists(pfad->getText()); pfad->release(); return ret; } bool Framework::FileIsDirectory( Text* pfad) // checks if the path is a directory { bool ret = FileIsDirectory(pfad->getText()); pfad->release(); return ret; } bool Framework::FilePathCreate( const char* pfad) // Creates a file in the path { Text pf = pfad; bool erst = 1; #ifdef WIN32 pf.ersetzen("//", "\\"); // Correct path separators pf.ersetzen("/", "\\"); for (int i = 0; i < pf.anzahlVon("\\"); ++i) // Create each directory if it does not exist { Text* t = pf.getTeilText(0, pf.positionVon("\\", i)); if (!t || !t->getLength()) { if (t) t->release(); continue; } if (!FileExists(dynamic_cast(t->getThis()))) # pragma warning(suppress : 6031) _mkdir(t->getText()); t->release(); if (pf.positionVon("\\", i) == pf.getLength() - 1) erst = 0; } #else pf.ersetzen("\\", "/"); // Correct path separators for (int i = 0; i < pf.anzahlVon("/"); ++i) // Create each directory if it does not exist { Text* t = pf.getTeilText(0, pf.positionVon("/", i)); if (!t || !t->getLength()) { if (t) t->release(); continue; } if (!FileExists(dynamic_cast(t->getThis()))) mkdir(t->getText(), 0777); t->release(); if (pf.positionVon("\\", i) == pf.getLength() - 1) erst = 0; } #endif if (erst) { std::ofstream f(pf, std::ios::binary); // Create file f.close(); } return FileExists(pf); } bool Framework::FileRemove(const char* pfad) // Deletes the specified file { Text pfa = pfad; #ifdef WIN32 pfa.ersetzen('\\', '/'); bool ret = 0; // check if file exists if (!FileIsDirectory(dynamic_cast(pfa.getThis()))) ret = DeleteFile(pfa.getText()) == 1; // delete file else { ret = 1; File* dat = new File(); dat->setFile(dynamic_cast(pfa.getThis())); int anz = dat->getUnterdateiAnzahl(); RCArray* liste = dat->getFileList(); for (int i = 0; i < anz; ++i) { Text* pf = new Text(pfa.getText()); if (pf->getText()[pf->getLength() - 1] != '/') pf->append("/"); pf->append(*liste->z(i)); if (ret) ret = FileRemove(pf); else FileRemove(pf); } liste->release(); dat->release(); if (ret) ret = RemoveDirectory(pfa.getText()) == 1; else RemoveDirectory(pfa.getText()); } return ret; #else pfa.ersetzen('\\', '/'); bool ret = 0; // check if file exists if (!FileIsDirectory(dynamic_cast(pfa.getThis()))) ret = std::remove(pfa.getText()) == 0; // delete file else { ret = 1; File* dat = new File(); dat->setFile(dynamic_cast(pfa.getThis())); int anz = dat->getUnterdateiAnzahl(); RCArray* liste = dat->getFileList(); for (int i = 0; i < anz; ++i) { Text* pf = new Text(pfa.getText()); if (pf->getText()[pf->getLength() - 1] != '/') pf->append("/"); pf->append(liste->get(i)); if (ret) ret = FileRemove(pf); else FileRemove(pf); } liste->release(); dat->release(); if (ret) ret = std::remove(pfa.getText()) == 0; else std::remove(pfa.getText()); } return ret; #endif } bool Framework::FileRename( const char* pfad_alt, const char* pfad_neu) // Renames the file { #ifdef WIN32 if (pfad_alt && pfad_neu && FileExists(pfad_alt)) { bool ret = 1; if (FileIsDirectory(pfad_alt)) { if (!FileExists(pfad_neu)) { Text tmp = pfad_neu; tmp += "/a"; FilePathCreate(tmp); FileRemove(tmp); } File d; d.setFile(pfad_alt); RCArray* list = d.getFileList(); int anz = list->getEntryCount(); for (int i = 0; i < anz; i++) { Text pf = pfad_neu; pf += "/"; pf += list->z(i)->getText(); Text pf_a = pfad_alt; pf_a += "/"; pf_a += list->z(i)->getText(); ret |= FileRename(pf_a, pf); } d.remove(); } else { if (FileExists(pfad_neu)) return 0; } ret |= MoveFile(pfad_alt, pfad_neu) == 1; // rename file return ret; } return 0; #else if (pfad_alt && pfad_neu && FileExists(pfad_alt)) { bool ret = 1; if (FileIsDirectory(pfad_alt)) { if (!FileExists(pfad_neu)) { Text tmp = pfad_neu; tmp += "/a"; FilePathCreate(tmp); FileRemove(tmp); } File d; d.setFile(pfad_alt); RCArray* list = d.getFileList(); int anz = list->getEntryCount(); for (int i = 0; i < anz; i++) { Text pf = pfad_neu; pf += "/"; pf += list->z(i)->getText(); Text pf_a = pfad_alt; pf_a += "/"; pf_a += list->z(i)->getText(); ret |= FileRename(pf_a, pf); } d.remove(); } else { if (FileExists(pfad_neu)) return 0; } ret |= rename(pfad_alt, pfad_neu) == 1; // rename file return ret; } return 0; #endif } bool Framework::FileExists(const char* pfad) // Checks if the file exists { #ifdef WIN32 bool ret = PathFileExists(pfad) != 0; return ret; #else std::ifstream file(pfad); if (file.good()) return 1; return 0; #endif } bool Framework::FileIsDirectory( const char* pfad) // checks if the path is a directory { #ifdef WIN32 WIN32_FIND_DATA wfd; HANDLE handle = FindFirstFile(pfad, &wfd); if (handle == INVALID_HANDLE_VALUE) return 0; FindClose(handle); return (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; #else struct stat path_stat; if (stat(pfad, &path_stat) != 0) return 0; if (S_ISDIR(path_stat.st_mode)) return 1; return 0; #endif }