File Manager / src / utils /

model-utils.c

  1. /*
  2. * Copyright 2014 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17.  
  18. #include "utils/model-utils.h"
  19. #include "utils/config.h"
  20. #include "utils/common-utils.h"
  21. #include "utils/logger.h"
  22.  
  23. #include <app.h>
  24. #include <ctype.h>
  25. #include <regex.h>
  26. #include <dirent.h>
  27. #include <unistd.h>
  28.  
  29. #define FM_NAME_PATTERN "[\\:*\"&<>'/]"
  30.  
  31. typedef struct _file_type_by_ext {
  32. const char *ext;
  33. file_type ftype;
  34. } file_type_by_ext;
  35.  
  36. static file_type_by_ext FILE_TYPE_BY_EXT[] = {
  37. {"3G2", FILE_TYPE_VIDEO},
  38. {"3GP", FILE_TYPE_VIDEO},
  39. {"3GPP", FILE_TYPE_VIDEO},
  40. {"AAC", FILE_TYPE_MUSIC},
  41. {"AMR", FILE_TYPE_VOICE},
  42. {"ASF", FILE_TYPE_VIDEO},
  43. {"AVI", FILE_TYPE_VIDEO},
  44. {"AWB", FILE_TYPE_VOICE},
  45. {"BMP", FILE_TYPE_IMAGE},
  46. {"DCF", FILE_TYPE_DRM},
  47. {"DIVX", FILE_TYPE_VIDEO},
  48. {"DOC", FILE_TYPE_DOC},
  49. {"DOCX", FILE_TYPE_DOC},
  50. {"G72", FILE_TYPE_MUSIC},
  51. {"GIF", FILE_TYPE_IMAGE},
  52. {"H263", FILE_TYPE_VIDEO},
  53. {"HTM", FILE_TYPE_HTML},
  54. {"HTML", FILE_TYPE_HTML},
  55. {"IMY", FILE_TYPE_SOUND},
  56. {"IPK", FILE_TYPE_APP},
  57. {"JAD", FILE_TYPE_JAVA},
  58. {"JAR", FILE_TYPE_JAVA},
  59. {"JPE", FILE_TYPE_IMAGE},
  60. {"JPEG", FILE_TYPE_IMAGE},
  61. {"JPG", FILE_TYPE_IMAGE},
  62. {"M3G", FILE_TYPE_FLASH},
  63. {"M4A", FILE_TYPE_MUSIC},
  64. {"MID", FILE_TYPE_SOUND},
  65. {"MIDI", FILE_TYPE_SOUND},
  66. {"MKA", FILE_TYPE_MUSIC},
  67. {"MKV", FILE_TYPE_VIDEO},
  68. {"MMF", FILE_TYPE_SOUND},
  69. {"MP3", FILE_TYPE_MUSIC},
  70. {"MP4", FILE_TYPE_VIDEO},
  71. {"MPEG", FILE_TYPE_VIDEO},
  72. {"MPG", FILE_TYPE_VIDEO},
  73. {"MXMF", FILE_TYPE_SOUND},
  74. {"OPML", FILE_TYPE_RSS},
  75. {"PDF", FILE_TYPE_PDF},
  76. {"PEM", FILE_TYPE_CERTIFICATION},
  77. {"PJPEG", FILE_TYPE_IMAGE},
  78. {"PNG", FILE_TYPE_IMAGE},
  79. {"PPT", FILE_TYPE_PPT},
  80. {"PPTX", FILE_TYPE_PPT},
  81. {"SCN", FILE_TYPE_MOVIE_MAKER},
  82. {"SDP", FILE_TYPE_VIDEO},
  83. {"SMP", FILE_TYPE_SOUND},
  84. {"SPF", FILE_TYPE_SOUND},
  85. {"SPM", FILE_TYPE_SOUND},
  86. {"SVG", FILE_TYPE_SVG},
  87. {"SVGZ", FILE_TYPE_SVG},
  88. {"SWF", FILE_TYPE_FLASH},
  89. {"THM", FILE_TYPE_THEME},
  90. {"TXT", FILE_TYPE_TXT},
  91. {"VBM", FILE_TYPE_VBOOKMARK},
  92. {"VCF", FILE_TYPE_VCONTACT},
  93. {"VCS", FILE_TYPE_VCALENDAR},
  94. {"VNT", FILE_TYPE_VNOTE},
  95. {"WAV", FILE_TYPE_SOUND},
  96. {"WBMP", FILE_TYPE_IMAGE},
  97. {"WGT", FILE_TYPE_WGT},
  98. {"WMA", FILE_TYPE_MUSIC},
  99. {"WMV", FILE_TYPE_VIDEO},
  100. {"XHTML", FILE_TYPE_HTML},
  101. {"XLS", FILE_TYPE_EXCEL},
  102. {"XLSX", FILE_TYPE_EXCEL},
  103. {"XMF", FILE_TYPE_SOUND}
  104. };
  105.  
  106. enum {
  107. FILE_TYPE_BY_EXT_ITEM_SIZE = sizeof(file_type_by_ext),
  108. FILE_TYPE_BY_EXT_LENGTH = sizeof(FILE_TYPE_BY_EXT) / FILE_TYPE_BY_EXT_ITEM_SIZE,
  109. MAX_EXT_LENGTH = 8
  110. };
  111.  
  112. static char *icon_array[FILE_TYPE_MAX] = {
  113. [FILE_TYPE_DIR] = FM_ICON_FOLDER,
  114. [FILE_TYPE_IMAGE] = FM_ICON_IMAGE,
  115. [FILE_TYPE_VIDEO] = FM_ICON_VIDEO,
  116. [FILE_TYPE_MUSIC] = FM_ICON_MUSIC,
  117. [FILE_TYPE_SOUND] = FM_ICON_SOUND,
  118. [FILE_TYPE_PDF] = FM_ICON_PDF,
  119. [FILE_TYPE_PPT] = FM_ICON_PPT,
  120. [FILE_TYPE_VOICE] = FM_ICON_VOICE,
  121. [FILE_TYPE_TXT] = FM_ICON_TXT,
  122. [FILE_TYPE_VNOTE] = FM_ICON_VNOTE,
  123. };
  124.  
  125. static int _model_utils_file_type_by_ext_compare(const void *key, const void *elem);
  126. static file_type _model_utils_get_category_by_file_ext(const char *file_ext, const char *fullpath);
  127. static int _model_utils_is_valid_name(const char *filename);
  128.  
  129. int model_utils_is_path_valid(const char *path, Eina_Bool is_dir)
  130. {
  131. int result = RESULT_TYPE_OK;
  132. if (!path) {
  133. return RESULT_TYPE_INVALID_PATH;
  134. }
  135.  
  136. size_t length = strlen(path);
  137. if (length == 0 || path[0] != '/') {
  138. return RESULT_TYPE_INVALID_PATH;
  139. }
  140.  
  141. if (is_dir == EINA_TRUE) {
  142. if ((path[length - 1] == '/') && (length > 1)) {
  143. return RESULT_TYPE_INVALID_PATH;
  144. }
  145. }
  146.  
  147. const char *file_name = NULL;
  148. file_name = common_util_get_filename(path);
  149. result = _model_utils_is_valid_name(file_name);
  150.  
  151. if (result != RESULT_TYPE_OK) {
  152. ERR("Is not valid dir path name");
  153. }
  154.  
  155. return result;
  156. }
  157.  
  158. Eina_Bool model_utils_is_file_exists(const char *filepath)
  159. {
  160. struct stat st;
  161.  
  162. if ((stat(filepath, &st) < 0) && (strcmp(filepath, "/"))) {
  163. return EINA_FALSE;
  164. }
  165.  
  166. return EINA_TRUE;
  167. }
  168.  
  169. Eina_Bool model_utils_file_is_dir(const char *filepath)
  170. {
  171. struct stat st;
  172.  
  173. if (stat(filepath, &st) < 0) {
  174. return EINA_FALSE;
  175. } if (S_ISDIR(st.st_mode)) {
  176. return EINA_TRUE;
  177. }
  178.  
  179. return EINA_FALSE;
  180. }
  181.  
  182. char *model_utils_get_dir_name(const char *filepath)
  183. {
  184. char *ptr = NULL;
  185. char buf[PATH_MAX] = {'\0'};
  186.  
  187. strncpy(buf, filepath, PATH_MAX);
  188. ptr = strrchr(buf, '/');
  189. if (!ptr) {
  190. return strdup(filepath);
  191. }
  192.  
  193. if (ptr == buf) {
  194. return strdup("/");
  195. }
  196.  
  197. *ptr = 0;
  198. return strdup(buf);
  199. }
  200.  
  201. static int _model_utils_is_valid_name(const char *filename)
  202. {
  203. int ret, z, cflags = 0;
  204. regex_t reg;
  205. regmatch_t pm[1];
  206. const size_t nmatch = 1;
  207.  
  208. if (strncmp(filename, ".", 1) == 0) {
  209. return RESULT_TYPE_INVALID_FILE_NAME;
  210. }
  211. z = regcomp(&reg, FM_NAME_PATTERN, cflags);
  212.  
  213. if (z != 0) {
  214. char ebuf[128];
  215. regerror(z, &reg, ebuf, sizeof(ebuf));
  216. fprintf(stderr, "%s: pattern '%s' \n", ebuf, FM_NAME_PATTERN);
  217. return RESULT_TYPE_INVALID_FILE_NAME;
  218. }
  219.  
  220. z = regexec(&reg, filename, nmatch, pm, 0);
  221. if (z == REG_NOMATCH) {
  222. ret = RESULT_TYPE_OK;
  223. } else {
  224. ret = RESULT_TYPE_INVALID_FILE_NAME;
  225. }
  226. regfree(&reg);
  227. return ret;
  228. }
  229.  
  230. static int _model_utils_file_type_by_ext_compare(const void *key, const void *elem)
  231. {
  232. return strcmp((const char *)key, ((const file_type_by_ext *)elem)->ext);
  233. }
  234.  
  235. static file_type _model_utils_get_category_by_file_ext(const char *file_ext, const char *fullpath)
  236. {
  237. file_type result = FILE_TYPE_ETC;
  238.  
  239. if (file_ext) {
  240. char ext_upper[MAX_EXT_LENGTH + 1];
  241. int i = 0;
  242.  
  243. {
  244. const int skip = (file_ext[0] == '.') ? 1 : 0;
  245. while ((file_ext[i + skip] != '\0') && (i < MAX_EXT_LENGTH)) {
  246. ext_upper[i] = toupper(file_ext[i + skip]);
  247. ++i;
  248. }
  249. ext_upper[i] = '\0';
  250. }
  251.  
  252. if (i > 0) {
  253. file_type_by_ext *const item = bsearch(ext_upper,
  254. FILE_TYPE_BY_EXT,
  255. FILE_TYPE_BY_EXT_LENGTH,
  256. FILE_TYPE_BY_EXT_ITEM_SIZE,
  257. _model_utils_file_type_by_ext_compare);
  258.  
  259. if (item) {
  260. result = item->ftype;
  261. }
  262. }
  263. }
  264. return result;
  265. }
  266.  
  267. int model_utils_get_file_category(const char *filepath, file_type *category)
  268. {
  269. if (model_utils_is_file_exists(filepath)) {
  270. *category = FILE_TYPE_DIR;
  271. return RESULT_TYPE_OK;
  272. }
  273.  
  274. const char *filename = common_util_get_filename(filepath);
  275. if (!filename) {
  276. *category = FILE_TYPE_NONE;
  277. return RESULT_TYPE_INVALID_ARG;
  278. }
  279.  
  280. const char *ext = strrchr(filename, '.');
  281. if ((ext) && (ext != filename) && (strlen(ext) != 1)) {
  282. *category = _model_utils_get_category_by_file_ext(ext + 1, filepath);
  283. return RESULT_TYPE_OK;
  284. }
  285.  
  286. *category = FILE_TYPE_NONE;
  287. return RESULT_TYPE_FAIL;
  288. }
  289.  
  290. const char *model_utils_get_default_icon_name(file_type ftype)
  291. {
  292. const char *icon_name = FM_ICON_DEFAULT;
  293.  
  294. if (icon_array[ftype]) {
  295. icon_name = icon_array[ftype];
  296. }
  297.  
  298. return icon_name;
  299. }
  300.  
  301. storage_type model_utils_get_storage_type(const char *fullpath)
  302. {
  303. char *buf = model_utils_get_phone_path();
  304.  
  305. const size_t len_phone = strlen(buf);
  306. const size_t len_memory = strlen(FM_MEMORY_FOLDER);
  307. storage_type storage = STORAGE_TYPE_NONE;
  308.  
  309. if (strncmp(fullpath, buf, len_phone) == 0) {
  310. storage = STORAGE_TYPE_PHONE;
  311. } else if (strncmp(fullpath, FM_MEMORY_FOLDER, len_memory) == 0) {
  312. storage = STORAGE_TYPE_MMC;
  313. } else {
  314. storage = STORAGE_TYPE_NONE;
  315. }
  316.  
  317. free(buf);
  318.  
  319. return storage;
  320. }
  321.  
  322. char *model_utils_get_public_file_path(const char *original_path)
  323. {
  324. RETVM_IF(!original_path, NULL , "Input original path is NULL");
  325.  
  326. char *buf = model_utils_get_phone_path();
  327. char *path = NULL;
  328.  
  329. const char *label = NULL;
  330. const char *folder = NULL;
  331.  
  332. const storage_type storage = model_utils_get_storage_type(original_path);
  333. switch (storage) {
  334. case STORAGE_TYPE_PHONE:
  335. label = FM_PHONE_LABEL;
  336. folder = buf;
  337. break;
  338. case STORAGE_TYPE_MMC:
  339. label = FM_MEMORY_LABEL;
  340. folder = FM_MEMORY_FOLDER;
  341. break;
  342. default:
  343. ERR("Failed to get public path");
  344. free(buf);
  345. return NULL;
  346. }
  347.  
  348. path = common_util_strconcat(label, original_path + strlen(folder), "/", NULL);
  349. free(buf);
  350.  
  351. return path;
  352. }
  353.  
  354. int model_utils_launch_file(const node_info *file_info)
  355. {
  356. RETVM_IF(!file_info, RESULT_TYPE_INVALID_ARG, "File info is NULL");
  357.  
  358. int result = RESULT_TYPE_FAIL;
  359.  
  360. RETVM_IF(!file_info->name || !file_info->parent_path, result, "File info data is not correct");
  361.  
  362. char *fullpath = common_util_strconcat(file_info->parent_path, "/", file_info->name, NULL);
  363. RETVM_IF(!fullpath, result, "Generate full path to file failed");
  364.  
  365. app_control_h app_ctrl = NULL;
  366.  
  367. /* app control create */
  368. int ret = app_control_create(&app_ctrl);
  369. RETVM_IF(ret != APP_CONTROL_ERROR_NONE, result, "Failed to create app control. [0x%x]", ret);
  370.  
  371. /* app control set URI */
  372. file_type category = file_info->type;
  373. if (category == FILE_TYPE_HTML) {
  374. char *html_path = common_util_strconcat("file://", fullpath, NULL);
  375. ret = app_control_set_uri(app_ctrl, html_path);
  376. free(html_path);
  377. } else if (category == FILE_TYPE_IMAGE) {
  378. app_control_add_extra_data(app_ctrl, "View By", "By Folder");
  379. ret = app_control_set_uri(app_ctrl, fullpath);
  380. } else {
  381. ret = app_control_set_uri(app_ctrl, fullpath);
  382. }
  383.  
  384. if (ret != APP_CONTROL_ERROR_NONE) {
  385. ERR("Set app control uri failed. [0x%x]", ret);
  386. app_control_destroy(app_ctrl);
  387. free(fullpath);
  388. return result;
  389. }
  390.  
  391. /* app control set operation */
  392. ret = app_control_set_operation(app_ctrl, APP_CONTROL_OPERATION_VIEW);
  393. if (ret != APP_CONTROL_ERROR_NONE) {
  394. ERR("Set app control operation failed. [0x%x]", ret);
  395. app_control_destroy(app_ctrl);
  396. free(fullpath);
  397. return result;
  398. }
  399.  
  400. /* app control launch request */
  401. ret = app_control_send_launch_request(app_ctrl, NULL, NULL);
  402. if (ret == APP_CONTROL_ERROR_APP_NOT_FOUND) {
  403. ERR("App control file not found. [0x%x]", ret);
  404. result = RESULT_TYPE_APP_CTRL_NOT_FOUND;
  405. } else if (ret != APP_CONTROL_ERROR_NONE) {
  406. ERR("App control launch failed. [0x%x]", ret);
  407. result = RESULT_TYPE_APP_CTRL_LAUNCH_FAILED;
  408. } else {
  409. result = RESULT_TYPE_OK;
  410. }
  411.  
  412. app_control_destroy(app_ctrl);
  413. free(fullpath);
  414.  
  415. return result;
  416. }
  417.  
  418. storage_type model_utils_is_root_path(const char *fullpath)
  419. {
  420. RETVM_IF(!fullpath, STORAGE_TYPE_NONE , "Input fullpath is NULL");
  421.  
  422. char *buf = model_utils_get_phone_path();
  423. bool is_phone_storage = (strcmp(fullpath, buf) == 0);
  424. free(buf);
  425.  
  426. if (is_phone_storage) {
  427. return STORAGE_TYPE_PHONE;
  428. } else if (!strcmp(fullpath, FM_MEMORY_FOLDER)) {
  429. return STORAGE_TYPE_MMC;
  430. } else {
  431. return STORAGE_TYPE_NONE;
  432. }
  433. }
  434.  
  435. int model_utils_read_dir(const char *dir_path, Eina_List **dir_list, Eina_List **file_list)
  436. {
  437. char *buf = NULL;
  438. struct dirent *ent = NULL;
  439.  
  440. RETVM_IF(!dir_path, RESULT_TYPE_INVALID_ARG, "dir_path is NULL");
  441. RETVM_IF(!dir_list, RESULT_TYPE_INVALID_ARG, "dir_list is NULL");
  442. RETVM_IF(!file_list, RESULT_TYPE_INVALID_ARG, "file_list is NULL");
  443.  
  444. DIR *const pDir = opendir(dir_path);
  445. RETVM_IF(!pDir, RESULT_TYPE_DIR_NOT_FOUND, "Failed to open dir %s", dir_path);
  446.  
  447. buf = model_utils_get_phone_path();
  448.  
  449. while ((ent = readdir(pDir)) && ent) {
  450. int skip = ((strncmp(ent->d_name, ".", 1) == 0) ||
  451. (strncmp(ent->d_name, "..", 2) == 0));
  452.  
  453. skip = skip || ((ent->d_type != DT_DIR) && (ent->d_type != DT_REG));
  454.  
  455. skip = skip || ((ent->d_type == DT_DIR) &&
  456. (strcmp(dir_path, buf) == 0) &&
  457. (strcmp(ent->d_name, FM_DEBUG_FOLDER) == 0));
  458.  
  459. node_info *const pNode = skip ? NULL : calloc(1, sizeof(node_info));
  460.  
  461. if (pNode) {
  462. pNode->parent_path = strdup(dir_path);
  463. pNode->name = strdup(ent->d_name);
  464. pNode->is_selected = EINA_FALSE;
  465.  
  466. if (ent->d_type == DT_DIR) {
  467. pNode->type = FILE_TYPE_DIR;
  468. } else {
  469. model_utils_get_file_category(ent->d_name, &(pNode->type));
  470. }
  471.  
  472. if (pNode->type == FILE_TYPE_DIR) {
  473. *dir_list = eina_list_append(*dir_list, pNode);
  474. } else {
  475. *file_list = eina_list_append(*file_list, pNode);
  476. }
  477. }
  478. }
  479.  
  480. closedir(pDir);
  481.  
  482. free(buf);
  483.  
  484. return RESULT_TYPE_OK;
  485. }
  486.  
  487. char *model_utils_get_phone_path(void)
  488. {
  489. register struct passwd *pw;
  490. register uid_t uid;
  491. char *buf = calloc(MAXPATHLEN, sizeof(char));
  492.  
  493. uid = geteuid();
  494. pw = getpwuid (uid);
  495. if (pw) {
  496. dlog_print(DLOG_INFO, LOG_TAG, "[%s:%d] The name: %s", __FILE__, __LINE__, pw->pw_name);
  497. snprintf(buf, MAXPATHLEN, FM_PHONE_FOLDER_FORMAT, pw->pw_name);
  498.  
  499. return buf;
  500. }
  501.  
  502. return NULL;
  503.  
  504. }