filefunctions.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. #include "filefunctions.h"
  2. #include "debugging.h"
  3. #include "exif.h"
  4. #include <string>
  5. #include <algorithm>
  6. #include <cstdio>
  7. #include <iostream>
  8. #include <sstream>
  9. #include <iomanip>
  10. #include <locale>
  11. using namespace filefunctions;
  12. std::string filefunctions::filefunctions_wd;
  13. COMMAND_FLAGS filefunctions::operator|(filefunctions::COMMAND_FLAGS a, filefunctions::COMMAND_FLAGS b)
  14. {
  15. return COMMAND_FLAGS(int(a)|int(b));
  16. }
  17. #ifdef __linux__
  18. // Linux methods
  19. Ej implementerat
  20. #elif _WIN32
  21. // Windows methods
  22. #include <windows.h>
  23. time_t filetime_to_unixtime(FILETIME const &t)
  24. {
  25. //FILETIME t;
  26. //FileTimeToLocalFileTime(&utc_t, &t);
  27. LARGE_INTEGER big_time;
  28. time_t unix_time;
  29. big_time.HighPart = t.dwHighDateTime;
  30. big_time.LowPart = t.dwLowDateTime;
  31. unix_time = big_time.QuadPart/10000000-11644473600;
  32. unix_time += 3600; // UTC+1
  33. DEBUG("__FILETIME__ " << big_time.QuadPart);
  34. return unix_time;
  35. }
  36. tm* get_exif_time(std::string path, long file_size)
  37. {
  38. FILE *filen = fopen(path.c_str(), "rb");
  39. if (filen == nullptr)
  40. {
  41. DEBUG("__GET_EXIF_TIME__ Could not find file: " << path);
  42. return nullptr;
  43. }
  44. DEBUG("__GET_EXIF_TIME__ Opened file: " << path);
  45. /*
  46. fseek(filen, 0, SEEK_END);
  47. unsigned long file_size = ftell(filen);
  48. rewind(filen);
  49. unsigned char *buf = new unsigned char[file_size];
  50. DEBUG("__GET_EXIF_TIME__ File size: " << file_size);
  51. if (fread(buf, 1, file_size, filen) != file_size)
  52. {
  53. DEBUG("__GET_EXIF_TIME__ Could not read file");
  54. delete[] buf;
  55. fclose(filen);
  56. return nullptr;
  57. }
  58. fclose(filen);*/
  59. DEBUG("__GET_EXIF_TIME__ File size: " << file_size);
  60. unsigned int shortened = file_size > 0x10000 ? 0x10000 : file_size;
  61. DEBUG("__GET_EXIF_TIME__ Shortened size: " << shortened);
  62. unsigned char *buf = new unsigned char[shortened];
  63. if (fread(buf, 1, shortened, filen) != shortened)
  64. {
  65. delete[] buf;
  66. fclose(filen);
  67. ASSERT("__GET_EXIF_TIME__ Could not read file");
  68. return nullptr;
  69. }
  70. fclose(filen);
  71. easyexif::EXIFInfo exif;
  72. if(exif.parseFrom(buf, shortened))
  73. {
  74. delete[] buf;
  75. ASSERT("__GET_EXIF_TIME__ Could not parse file");
  76. return nullptr;
  77. }
  78. delete[] buf;
  79. DEBUG("__GET_EXIF_TIME__ File parsed!");
  80. if(exif.DateTimeOriginal.size()==0)
  81. {
  82. DEBUG("__GET_EXIF_TIME__ No original datetime found!");
  83. delete[] buf;
  84. return nullptr;
  85. }
  86. tm *result = new tm;
  87. //tm *result = (tm*)malloc(sizeof(tm));
  88. sscanf(exif.DateTimeOriginal.c_str(), "%d:%d:%d %d:%d:%d", &result->tm_year, &result->tm_mon, &result->tm_mday, &result->tm_hour, &result->tm_min, &result->tm_sec);
  89. DEBUG("__GET_EXIF_TIME__ DateTime: " << exif.DateTimeOriginal.c_str());
  90. DEBUG("__GET_EXIF_TIME__ year: " << result->tm_year);
  91. DEBUG("__GET_EXIF_TIME__ month: " << result->tm_mon);
  92. DEBUG("__GET_EXIF_TIME__ date: " << result->tm_mday);
  93. DEBUG("__GET_EXIF_TIME__ hour: " << result->tm_hour);
  94. DEBUG("__GET_EXIF_TIME__ minute: " << result->tm_min);
  95. DEBUG("__GET_EXIF_TIME__ second: " << result->tm_sec);
  96. result->tm_year -= 1900;
  97. result->tm_mon -= 1;
  98. tm dont_touch_my_time = *result;
  99. time_t unix_time = mktime(result);
  100. *result = dont_touch_my_time;
  101. DEBUG("__GET_EXIF_TIME__ Time: " << unix_time);
  102. // Sort of a sanity check
  103. if(unix_time == -1)
  104. {
  105. delete result;
  106. return nullptr;
  107. }//*/
  108. return result;
  109. }
  110. STATUS_CODE filefunctions::cd(std::string const &path_arg, COMMAND_FLAGS flags)
  111. {
  112. DWORD attr;
  113. std::string path;
  114. if(flags&CF_RELATIVE)
  115. {
  116. path = filefunctions_wd;
  117. if(path.length() == 0)
  118. {
  119. int path_len = GetCurrentDirectory(0, nullptr);
  120. LPTSTR temp = new TCHAR[path_len+1];
  121. if(!GetCurrentDirectory(path_len+1, temp))
  122. return SC_INVALID_PATH;
  123. path = std::string(temp);
  124. DEBUG("__CD__ GetCurrentDirectory() = " << temp);
  125. delete[] temp;
  126. }
  127. if(path_arg.length())
  128. path += "\\" + path_arg;
  129. }
  130. else
  131. {
  132. path = path_arg;
  133. }
  134. attr = GetFileAttributes(path.c_str());
  135. DEBUG("__CD__ Path: " << path);
  136. DEBUG("__CD__ Attr: " << std::hex << attr);
  137. if(attr != INVALID_FILE_ATTRIBUTES && attr&FILE_ATTRIBUTE_DIRECTORY)
  138. {
  139. filefunctions_wd = path;
  140. return SC_SUCCESS;
  141. }
  142. return SC_INVALID_PATH;
  143. }
  144. STATUS_CODE filefunctions::mv(std::string const &src_arg, std::string const &dest_arg, COMMAND_FLAGS flags)
  145. {
  146. std::string src, dest;
  147. DWORD attr;
  148. if(flags & CF_RELATIVE)
  149. {
  150. src = filefunctions_wd;
  151. dest = filefunctions_wd;
  152. if(src.length())
  153. src += "\\" + src_arg;
  154. if(dest.length())
  155. dest += "\\" + dest_arg;
  156. }
  157. else
  158. {
  159. src = src_arg;
  160. dest = dest_arg;
  161. }
  162. DEBUG("__MV__ Source: " << src);
  163. DEBUG("__MV__ Destination: " << dest);
  164. attr = GetFileAttributes(src.c_str());
  165. if (attr == INVALID_FILE_ATTRIBUTES)
  166. {
  167. DEBUG("__MV__ Source does not exist");
  168. return SC_DOES_NOT_EXIST;
  169. }
  170. if(mkdir(dest.substr(0,dest.find_last_of("/\\"))))
  171. {
  172. DEBUG("__MV__ Could not determine destination directory");
  173. return SC_INVALID_DESTINATION;
  174. }
  175. if(MoveFile(src.c_str(), dest.c_str()))
  176. {
  177. DEBUG("__MV__ Moved file\n\n");
  178. return SC_SUCCESS;
  179. }
  180. if(GetLastError() == ERROR_ALREADY_EXISTS)
  181. {
  182. DEBUG("__MV__ Target already exists");
  183. return SC_ALREADY_EXISTS;
  184. }
  185. return SC_OTHER_FAILIURE;
  186. }
  187. STATUS_CODE filefunctions::mkdir(std::string const &arg_path, COMMAND_FLAGS flags)
  188. {
  189. std::string path;
  190. if(flags & CF_RELATIVE)
  191. {
  192. path = filefunctions_wd;
  193. if(arg_path.length())
  194. path += "\\" + arg_path;
  195. }
  196. else
  197. {
  198. path = arg_path;
  199. }
  200. DEBUG("__MKDIR__ Path: " << path);
  201. DWORD attr = GetFileAttributes(path.c_str());
  202. if(attr != INVALID_FILE_ATTRIBUTES && attr&FILE_ATTRIBUTE_DIRECTORY)
  203. {
  204. DEBUG("__MKDIR__ SUCCESS Attr: " << attr);
  205. return SC_SUCCESS;
  206. }
  207. else if(attr != INVALID_FILE_ATTRIBUTES)
  208. {
  209. DEBUG("__MKDIR__ FAILED Attr: " << attr);
  210. return SC_IS_NOT_DIRECTORY;
  211. }
  212. size_t parent_separator = path.find_last_of("/\\");
  213. if(parent_separator == std::string::npos)
  214. {
  215. DEBUG("__MKDIR__ Invalid path");
  216. return SC_INVALID_PATH;
  217. }
  218. std::string parent = path.substr(0,parent_separator);
  219. DEBUG("__MKDIR__ Parent: " << parent);
  220. if(mkdir(parent) == SC_SUCCESS)
  221. {
  222. if(CreateDirectory(path.c_str(), nullptr))
  223. {
  224. DEBUG("__MKDIR__ Created directory: " << path);
  225. return SC_SUCCESS;
  226. }
  227. else
  228. {
  229. DEBUG("__MKDIR__ CreateDirectory failed");
  230. return SC_OTHER_FAILIURE;
  231. }
  232. }
  233. else
  234. {
  235. DEBUG("__MKDIR__ mkdir(" << parent << ") failed");
  236. return SC_OTHER_FAILIURE;
  237. }
  238. }
  239. //STATUS_CODE filefunctions::rm(std::string const &path, COMMAND_FLAGS flags = CF_NONE);
  240. std::string filefunctions::pwd(void)
  241. {
  242. return filefunctions_wd;
  243. }
  244. STATUS_CODE filefunctions::ls(std::string path_arg, std::queue<File_Struct> &content, COMMAND_FLAGS flags)
  245. {
  246. std::string path;
  247. if(flags & CF_RELATIVE)
  248. {
  249. path = filefunctions_wd;
  250. if(path_arg.length())
  251. path += path_arg;
  252. }
  253. else
  254. {
  255. path = path_arg;
  256. }
  257. DEBUG("__LS__ ls(" << path << ")");
  258. DWORD attr = GetFileAttributes(path.c_str());
  259. if(attr != INVALID_FILE_ATTRIBUTES && !(attr&FILE_ATTRIBUTE_DIRECTORY))
  260. return SC_IS_NOT_DIRECTORY;
  261. std::string path_joker = path + "\\*";
  262. WIN32_FIND_DATA file_data;
  263. HANDLE status = FindFirstFile(path_joker.c_str(), &file_data);
  264. if(status == INVALID_HANDLE_VALUE)
  265. return SC_OTHER_FAILIURE;
  266. do
  267. {
  268. File_Struct temp;
  269. temp.modified = nullptr;
  270. temp.taken = nullptr;
  271. temp.file_ending = "";
  272. temp.path = path + "\\" + file_data.cFileName;
  273. if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  274. {
  275. DEBUG("__LS__ Found directory!");
  276. DEBUG("__LS__ Directory: \"" << temp.path << "\"");
  277. if(flags&CF_RECURSIVE)
  278. {
  279. if(strcmp(file_data.cFileName, ".")==0 || strcmp(file_data.cFileName, "..")==0)
  280. {
  281. DEBUG("__LS__ Ignoring directory . or ..");
  282. }
  283. else
  284. {
  285. INFO("__LS__ Found directory. Going in!\n");
  286. ls(temp.path, content, CF_RECURSIVE);
  287. }
  288. }
  289. else
  290. {
  291. DEBUG("__LS__ Ignoring directory, not recursive");
  292. }
  293. }
  294. else
  295. {
  296. DEBUG("__LS__ Found file!");
  297. INFO("__LS__ File: \"" << temp.path << "\"");
  298. time_t unix_time = filetime_to_unixtime(file_data.ftLastWriteTime);
  299. DEBUG("__LS__ Modified time: " << std::dec << unix_time);
  300. if(unix_time < 800000000 || unix_time > 3500000000)
  301. {
  302. delete temp.modified;
  303. temp.modified = nullptr;
  304. }
  305. else
  306. {
  307. temp.modified = new tm;
  308. memcpy(temp.modified, gmtime(&unix_time), sizeof(tm));
  309. }
  310. temp.file_ending = temp.path.substr(temp.path.find_last_of('.')+1);
  311. std::transform(temp.file_ending.begin(), temp.file_ending.end(), temp.file_ending.begin(), ::tolower);
  312. DEBUG("__LS__ File ending: " << temp.file_ending);
  313. if(temp.file_ending == "jpeg" || temp.file_ending == "jpg")
  314. {
  315. temp.file_ending = "jpg";
  316. DEBUG("__LS__ Found JPEG-file, decoding EXIF");
  317. LARGE_INTEGER dryg;
  318. dryg.HighPart = file_data.nFileSizeHigh;
  319. dryg.LowPart = file_data.nFileSizeLow;
  320. temp.taken = get_exif_time(temp.path, dryg.QuadPart);
  321. if(temp.taken)
  322. {
  323. DEBUG("__LS__ year: " << temp.taken->tm_year);
  324. DEBUG("__LS__ month: " << temp.taken->tm_mon);
  325. DEBUG("__LS__ date: " << temp.taken->tm_mday);
  326. DEBUG("__LS__ hour: " << temp.taken->tm_hour);
  327. DEBUG("__LS__ minute: " << temp.taken->tm_min);
  328. DEBUG("__LS__ second: " << temp.taken->tm_sec);
  329. }
  330. }
  331. content.push(temp);
  332. }
  333. DEBUG("__LS__ Checking for other files\n");
  334. } while (FindNextFile(status, &file_data) != 0);
  335. DEBUG("__LS__ Finnished ls()\n\n");
  336. return SC_SUCCESS;
  337. }
  338. #else
  339. // Fail?
  340. Hård fail som fan!
  341. #endif // __linux__