00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00023 #include <ctype.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026
00027 #include <dirent.h>
00028 #include <sys/stat.h>
00029 #include <sys/types.h>
00030 #include <time.h>
00031 #include <errno.h>
00032 #include <string.h>
00033 #include <strings.h>
00034 #include <unistd.h>
00035 #include <linux/limits.h>
00036 #include <sys/vfs.h>
00037
00038 #include <glib/gprintf.h>
00039 #include <gtk/gtk.h>
00040
00041 #include <libermanifest/ermanifest.h>
00042
00043 #include "contentListerLog.h"
00044 #include "erConnect.h"
00045 #include "system.h"
00046 #include "gtkPincodeScreen.h"
00047 #include "control.h"
00048 #include "erMdsContent.h"
00049 #include "languages.h"
00050 #include "metadataStoreManager.h"
00051
00052 #define MOBIPOCKET_CHECK1_OFFSET 0x3C
00053 #define MOBIPOCKET_FIRST_RECORD 0x4E
00054 #define MOBIPOCKET_CHECK2_OFFSET 0x10
00055 #define MOBIPOCKET_ENCODING_OFFSET 0x1C
00056 #define MOBIPOCKET_CHECK3_OFFSET 0x24
00057 #define MOBIPOCKET_TITLE_RECORD_OFFSET 0x54
00058 #define MOBIPOCKET_TITLE_LENGTH_OFFSET 0x58
00059 #define MOBIPOCKET_PDB_TITLE_OFFSET 0x00
00060 #define MOBIPOCKET_PDB_TITLE_LENGTH 0x20
00061
00062 #define MOBIPOCKET_ENCODING_UTF8 0xFDE9
00063 #define MOBIPOCKET_ENCODING_WIN1252 0x04E4
00064
00065
00066 typedef struct
00067 {
00068 const char* path;
00069 int len;
00070 } trusted_device_t;
00071
00072 static trusted_device_t g_trusted_devices[]
00073 = {
00074 { "/mnt/free" },
00075 { "/mnt/card" },
00076 { "/mnt/cf" },
00077 { "/mnt/usb" },
00078 { "/media/card" },
00079 { "/media/cf" },
00080 { NULL }
00081 };
00082
00083
00084 static int erClGetFileType(const char *szPath);
00085 static int erClGetSymlinkInfo(const char* szRealpath, mdsFsItemType_e* pFit);
00086
00087 static void mdsContentPreSort(GArray * contentItemArray, mdsSortStruct_t * sort);
00088 static void mdsContentPostSort(GArray * contentItemArray);
00089 static gint mdsFieldFsNameComparison(gconstpointer a, gconstpointer b, gpointer user_data);
00090 static gint mdsFieldGenericComparison(gconstpointer a, gconstpointer b, gpointer user_data);
00091 static int datecmp(const char* dateA, const char* dateB);
00092 static int sizecmp(const char* sizeA, const char* sizeB);
00093
00094 static void mdsFetchField(mdsFsItem_t * pFsItem, mdsSortStruct_t * sort, char *szField);
00095 static void mdsFetchFieldOfFile(mdsFsItem_t * pFsItem, mdsSortStruct_t * sort, char *szField);
00096 static void mdsFetchFieldOfFolder(mdsFsItem_t * pFsItem, mdsSortStruct_t * sort, char *szField);
00097 static void mdsFetchFieldOfContainer(mdsFsItem_t * pFsItem, mdsSortStruct_t * sort, char *szField);
00098 static void mdsFetchFieldOfSymlink(mdsFsItem_t * pFsItem, mdsSortStruct_t * sort, char *szField);
00099
00100 static void getFakeTitle(const char* szPath, char* szTitle);
00101 static int getSize(const char * pathName);
00102 static void getDate(const char *szPath, char *szDate);
00103 static void getExtName(const char*szPath, char*szExt);
00104 static gboolean getMobipocketTitle(const char* szPath, char* szTitle);
00105 static inline gboolean is_mobipocket_folder(const char * szPath, const int len);
00106
00107 static void displayItemSetDefault(clDisplayItem_t *displayItem);
00108 static void containerGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem);
00109 static void symlinkGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem);
00110 static void fileGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem);
00111 static void folderGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem);
00112
00113
00114 static inline gboolean extensionIsMobipocket(char *pExt)
00115 {
00116 return (gboolean) (strcasecmp(pExt, "mobi") == 0 ||
00117 strcasecmp(pExt, "prc") == 0 ||
00118 strcasecmp(pExt, "pdb") == 0 );
00119 }
00120
00121
00122
00123 const gchar* ctrl_is_trusted_path(const char* path)
00124 {
00125 const gchar* ret = NULL;
00126 trusted_device_t* pDevice;
00127
00128 static gboolean first_time = TRUE;
00129 static char* download_history = NULL;
00130 static int download_history_len = 0;
00131
00132
00133
00134 if (first_time)
00135 {
00136 char dirname[ERMDS_MAX_FILENAME_SIZE];
00137
00138
00139 for (pDevice = (trusted_device_t*)&g_trusted_devices[0] ; pDevice->path != NULL ; pDevice++)
00140 {
00141 pDevice->len = strlen(pDevice->path);
00142 }
00143
00144
00145 if (mdsGetRootLocation(st_DownloadHistory, dirname, sizeof(dirname)) > 0)
00146 {
00147 download_history = strdup(dirname);
00148 download_history_len = strlen(download_history);
00149 }
00150
00151
00152 first_time = FALSE;
00153 }
00154
00155
00156 for (pDevice = &g_trusted_devices[0] ; pDevice->path != NULL && ret == NULL ; pDevice++)
00157 {
00158 if (strncmp(path, pDevice->path, pDevice->len) == 0)
00159 {
00160
00161 ret = pDevice->path;
00162 }
00163 }
00164
00165
00166 if (ret == NULL && download_history)
00167 {
00168 if (strncmp(path, download_history, download_history_len) == 0)
00169 {
00170
00171 ret = download_history;
00172 }
00173 }
00174
00175
00176 return ret;
00177 }
00178
00179
00180
00181
00182
00183 int erMdsContentScan(GArray * dirArray, GArray ** contentItemArray)
00184 {
00185 gint nDir;
00186 guint initialArraySize = ERMDS_INITIAL_CONTENT_SCAN_ARRAY_SIZE;
00187 DIR *dirp;
00188 struct dirent *direntp;
00189 mdsFsItem_t fsItem;
00190 int ret = ERMDS_CONTENT_SCAN_OK;
00191
00192 CL_LOGPRINTF("entry");
00193
00194
00195 if (*contentItemArray == NULL)
00196 {
00197 CL_LOGPRINTF("Creating a new contentItemArray");
00198
00199
00200 *contentItemArray = g_array_sized_new(FALSE, FALSE, sizeof(mdsFsItem_t), initialArraySize);
00201 }
00202
00203 CL_LOGPRINTF("dirArray->len = %d", dirArray->len);
00204
00205
00206 for (nDir = 0; nDir < dirArray->len; nDir++)
00207 {
00208
00209 char *szDir = (char *) &g_array_index(dirArray, mdsDirectory_t, nDir);
00210
00211 if ((dirp = opendir(szDir)) == NULL)
00212 {
00213
00214 CL_WARNPRINTF("Could not open directory %s (error %s).", szDir, strerror(errno));
00215 }
00216 else
00217 {
00218 while ((direntp = readdir(dirp)) != NULL)
00219 {
00220
00221
00222
00223 if ((direntp->d_name[0] != (int) '.') && (direntp->d_name[0] != (int) '_')
00224 && (strcasecmp(MANIFEST_FILENAME, direntp->d_name) != 0))
00225 {
00226 gint nPathLength;
00227
00228 CL_LOGPRINTF("%s", direntp->d_name);
00229
00230
00231 nPathLength =
00232 g_snprintf(fsItem.szFilename, ERMDS_MAX_FILENAME_SIZE, "%s/%s", szDir, direntp->d_name);
00233 fsItem.sortField = NULL;
00234 fsItem.priority = 0;
00235
00236 if (nPathLength < ERMDS_MAX_FILENAME_SIZE)
00237 {
00238
00239
00240 int gft = erClGetFileType(fsItem.szFilename);
00241 switch (gft)
00242 {
00243 case GFT_FILE:
00244 fsItem.fit = mdsFitFile;
00245 break;
00246
00247 case GFT_DIR:
00248 {
00249 char szManifestPath[ERMDS_MAX_FILENAME_SIZE];
00250 struct stat statbuf;
00251
00252
00253 g_snprintf( szManifestPath, sizeof(szManifestPath),
00254 "%s/" MANIFEST_FILENAME,
00255 fsItem.szFilename );
00256
00257 if (stat(szManifestPath, &statbuf) == 0)
00258 {
00259 if (S_ISREG(statbuf.st_mode) != 0)
00260 {
00261 fsItem.fit = mdsFitContainer;
00262 }
00263 else
00264 {
00265 CL_WARNPRINTF("%s is not a regular file, default to folder type",
00266 szManifestPath);
00267 fsItem.fit = mdsFitFolder;
00268 }
00269 }
00270 else
00271 {
00272 fsItem.fit = mdsFitFolder;
00273 }
00274
00275
00276 if (is_mobipocket_folder(fsItem.szFilename, nPathLength))
00277 {
00278 CL_LOGPRINTF("Found Mobipocket: %s", fsItem.szFilename);
00279 fsItem.priority = MOBIPOCKET_FOLDER_SORT_PRIORITY;
00280 }
00281 }
00282 break;
00283
00284 case GFT_SYMLINK:
00285 fsItem.fit = mdsFitSymlink;
00286 break;
00287
00288 case GFT_NOSUCHFILE:
00289 case GFT_IGNORE:
00290 default:
00291 continue;
00292 }
00293
00294 if ((*contentItemArray)->len < ERMDS_MAX_CONTENT_SCAN_ARRAY_SIZE)
00295 {
00296 g_array_append_val(*contentItemArray, fsItem);
00297 }
00298 else
00299 {
00300 ret = ERMDS_CONTENT_SCAN_TOO_MANY_ITEMS;
00301 break;
00302 }
00303 }
00304 else
00305 {
00306 CL_ERRORPRINTF("Filename %s/%s too long. (nPathLength (%d) > %d)", szDir, direntp->d_name,
00307 nPathLength, ERMDS_MAX_FILENAME_SIZE);
00308 }
00309 }
00310 }
00311 closedir(dirp);
00312 }
00313 if (ret == ERMDS_CONTENT_SCAN_TOO_MANY_ITEMS)
00314 {
00315 return ret;
00316 }
00317 }
00318 return ret;
00319 }
00320
00321
00322
00323 int erMdsContentSort(GArray * contentItemArray, mdsSortStruct_t * sort)
00324 {
00325 int ret;
00326
00327 CL_LOGPRINTF("entry");
00328
00329 switch (sort->ft)
00330 {
00331 case mdsFieldFsName:
00332 g_array_sort_with_data(contentItemArray, mdsFieldFsNameComparison, (gpointer) sort);
00333 ret = ERMDS_CONTENT_SORT_OK;
00334 break;
00335
00336 case mdsFieldAuthor:
00337 case mdsFieldDate:
00338 case mdsFieldDescription:
00339 case mdsFieldFile:
00340 case mdsFieldTitle:
00341 case mdsFieldExtName:
00342 case mdsFieldSize:
00343 mdsContentPreSort(contentItemArray, sort);
00344 g_array_sort_with_data(contentItemArray, mdsFieldGenericComparison, (gpointer) sort);
00345 mdsContentPostSort(contentItemArray);
00346 ret = ERMDS_CONTENT_SORT_OK;
00347 break;
00348
00349 default:
00350 CL_ERRORPRINTF("No support for sorting of type %d", (int) sort->ft);
00351 ret = ERMDS_CONTENT_SORT_NOT_IMPLEMENTED;
00352 }
00353 return ret;
00354 }
00355
00356
00357 static void mdsContentPreSort(GArray * contentItemArray, mdsSortStruct_t * sort)
00358 {
00359 mdsFsItem_t *pFsItem;
00360 int i, total;
00361 char szField[ERMDS_MAX_FILENAME_SIZE];
00362 int len;
00363
00364 CL_LOGPRINTF("entry");
00365
00366 if (contentItemArray && sort)
00367 {
00368 total = contentItemArray->len;
00369 for (i = 0; i < total; i++)
00370 {
00371 pFsItem = &g_array_index(contentItemArray, mdsFsItem_t, i);
00372 if (pFsItem)
00373 {
00374
00375 if (pFsItem->sortField)
00376 {
00377 free(pFsItem->sortField);
00378 pFsItem->sortField = NULL;
00379 }
00380
00381 mdsFetchField(pFsItem, sort, szField);
00382 len = strlen(szField) + 1;
00383 pFsItem->sortField = (char *)malloc(len);
00384 if (pFsItem->sortField)
00385 {
00386 strcpy(pFsItem->sortField, szField);
00387 }
00388 else
00389 {
00390 CL_ERRORPRINTF("Can't malloc memory for pFsItem->sortField.");
00391 }
00392 }
00393 else
00394 {
00395 CL_ERRORPRINTF("Can't get the (%d)th pFsItem.", i);
00396 }
00397 }
00398 }
00399 }
00400
00401
00402 static void mdsContentPostSort(GArray * contentItemArray)
00403 {
00404 mdsFsItem_t *pFsItem;
00405 int i, total;
00406
00407 CL_LOGPRINTF("entry");
00408
00409 if (contentItemArray)
00410 {
00411 total = contentItemArray->len;
00412 for (i = 0; i < total; i++)
00413 {
00414 pFsItem = &g_array_index(contentItemArray, mdsFsItem_t, i);
00415 if (pFsItem)
00416 {
00417 if (pFsItem->sortField)
00418 {
00419 free(pFsItem->sortField);
00420 pFsItem->sortField = NULL;
00421 }
00422 }
00423 else
00424 {
00425 CL_ERRORPRINTF("Can't get the (%d)th pFsItem.", i);
00426 }
00427 }
00428 }
00429 }
00430
00431
00432
00433
00434
00435
00436
00437 static inline gboolean is_mobipocket_folder(const char * szPath, const int len)
00438 {
00439 const char *cp = &szPath[0];
00440
00441 if (len > MOBIPOCKET_FOLDER_LENGTH)
00442 {
00443 cp += (len - MOBIPOCKET_FOLDER_LENGTH);
00444 }
00445 else
00446 {
00447 return FALSE;
00448 }
00449
00450 if (strcmp(cp, MOBIPOCKET_FOLDER) == 0)
00451 {
00452 return TRUE;
00453 }
00454 else
00455 {
00456 return FALSE;
00457 }
00458 }
00459
00460
00461 static gint mdsFieldFsNameComparison(gconstpointer a, gconstpointer b, gpointer user_data)
00462 {
00463 mdsFsItem_t *pFsItemA = (mdsFsItem_t *) a;
00464 mdsFsItem_t *pFsItemB = (mdsFsItem_t *) b;
00465 mdsSortStruct_t *sort = (mdsSortStruct_t *) user_data;
00466 int ret;
00467
00468
00469
00470
00471
00472 if (pFsItemA->priority == pFsItemB->priority)
00473 {
00474 if (sort->ascending == 1)
00475 {
00476 ret = strcasecmp(pFsItemA->szFilename, pFsItemB->szFilename);
00477 }
00478 else
00479 {
00480 ret = strcasecmp(pFsItemB->szFilename, pFsItemA->szFilename);
00481 }
00482 }
00483 else if (pFsItemA->priority < pFsItemB->priority)
00484 {
00485 ret = 1;
00486 }
00487 else
00488 {
00489 ret = -1;
00490 }
00491
00492 return ret;
00493 }
00494
00495 static gint mdsFieldGenericComparison(gconstpointer a, gconstpointer b, gpointer user_data)
00496 {
00497 mdsFsItem_t *pFsItemA;
00498 mdsFsItem_t *pFsItemB;
00499 mdsSortStruct_t *sort;
00500 char *szFieldA = NULL;
00501 char *szFieldB = NULL;
00502 int ret = 0;
00503
00504 pFsItemA = (mdsFsItem_t *) a;
00505 pFsItemB = (mdsFsItem_t *) b;
00506 sort = (mdsSortStruct_t *) user_data;
00507
00508
00509
00510
00511
00512 if (pFsItemA->priority != pFsItemB->priority)
00513 {
00514 if (pFsItemA->priority < pFsItemB->priority)
00515 {
00516 return 1;
00517 }
00518 else
00519 {
00520 return -1;
00521 }
00522 }
00523
00524 szFieldA = pFsItemA->sortField;
00525 szFieldB = pFsItemB->sortField;
00526
00527 if (szFieldA && szFieldB)
00528 {
00529
00530 if (mdsFieldDate == sort->ft)
00531 {
00532 ret = datecmp(szFieldA, szFieldB);
00533 }
00534 else if (mdsFieldSize == sort->ft)
00535 {
00536 ret = sizecmp(szFieldA, szFieldB);
00537 }
00538 else
00539 {
00540 ret = strcasecmp(szFieldA, szFieldB);
00541 }
00542 }
00543 else if (szFieldA && NULL == szFieldB)
00544 {
00545 ret = 1;
00546 CL_LOGPRINTF("szFieldA && szFieldB == NULL");
00547 }
00548 else if (NULL == szFieldA && szFieldB)
00549 {
00550 ret = -1;
00551 CL_LOGPRINTF("szFieldA == NULL && szFieldB");
00552 }
00553 else
00554 {
00555 ret = 0;
00556 CL_LOGPRINTF("szFieldA == szFieldB == NULL");
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 if (0 == ret && mdsFieldTitle != sort->ft && mdsFieldFsName != sort->ft)
00578 {
00579 CL_LOGPRINTF("using default sorting type: Filename");
00580 ret = strcasecmp(pFsItemA->szFilename, pFsItemB->szFilename);
00581 }
00582
00583 if (sort->ascending == 0)
00584 {
00585 ret = 0 - ret;
00586 }
00587 CL_LOGPRINTF("ret = %d", ret);
00588 return ret;
00589 }
00590
00591
00592 static int datecmp(const char* dateA, const char* dateB)
00593 {
00594 struct tm tmA, tmB;
00595 time_t timeA, timeB;
00596 double diff = 0;
00597 char *string = NULL;
00598
00599 CL_LOGPRINTF("entry");
00600
00601 if (NULL == dateA || NULL == dateB)
00602 {
00603 CL_ERRORPRINTF("invalid arguments");
00604 return diff;
00605 }
00606
00607 string = strptime(dateA, "%Y-%m-%dT%H:%M:%S", &tmA);
00608 string = strptime(dateB, "%Y-%m-%dT%H:%M:%S", &tmB);
00609 timeA = mktime(&tmA);
00610 timeB = mktime(&tmB);
00611 diff = difftime(timeA, timeB);
00612
00613 return (int)diff;
00614 }
00615
00616
00617 static int sizecmp(const char* sizeA, const char* sizeB)
00618 {
00619 int nSizeA, nSizeB;
00620 int diff = 0;
00621
00622 CL_LOGPRINTF("entry");
00623
00624 if (NULL == sizeA || NULL == sizeB)
00625 {
00626 CL_ERRORPRINTF("invalid arguments");
00627 return diff;
00628 }
00629
00630 nSizeA = atoi(sizeA);
00631 nSizeB = atoi(sizeB);
00632 diff = nSizeA - nSizeB;
00633
00634 return diff;
00635 }
00636
00637
00638
00639
00640
00641
00642 static void mdsFetchField(mdsFsItem_t * pFsItem, mdsSortStruct_t * sort, char *szField)
00643 {
00644 if (NULL == pFsItem || NULL == sort || NULL == szField)
00645 {
00646 CL_ERRORPRINTF("invalid arguments");
00647 return;
00648 }
00649
00650 switch (pFsItem->fit)
00651 {
00652 case mdsFitFile:
00653 mdsFetchFieldOfFile(pFsItem, sort, szField);
00654 break;
00655 case mdsFitFolder:
00656 mdsFetchFieldOfFolder(pFsItem, sort, szField);
00657 break;
00658 case mdsFitSymlink:
00659 mdsFetchFieldOfSymlink(pFsItem, sort, szField);
00660 break;
00661 case mdsFitContainer:
00662 mdsFetchFieldOfContainer(pFsItem, sort, szField);
00663 break;
00664 default:
00665 CL_ERRORPRINTF("fit %d is not defined", pFsItem->fit);
00666 strcpy(szField, "");
00667 }
00668 }
00669
00670 static void mdsFetchFieldOfFile(mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char*szField)
00671 {
00672 CL_LOGPRINTF("entry");
00673
00674 int size = 0;
00675
00676 if (NULL == pFsItem || NULL == sort || NULL == szField)
00677 {
00678 CL_ERRORPRINTF("invalid arguments");
00679 return;
00680 }
00681 if (mdsFitFile != pFsItem->fit)
00682 {
00683 CL_ERRORPRINTF("invalid arguments");
00684 return;
00685 }
00686
00687 switch (sort->ft)
00688 {
00689 case mdsFieldFsName:
00690 strcpy(szField, pFsItem->szFilename);
00691 break;
00692 case mdsFieldTitle:
00693 getFakeTitle(pFsItem->szFilename, szField);
00694 break;
00695 case mdsFieldDate:
00696 getDate(pFsItem->szFilename, szField);
00697 break;
00698 case mdsFieldSize:
00699 size = getSize(pFsItem->szFilename);
00700 g_snprintf(szField, ERMDS_MAX_FILENAME_SIZE, "%d", size);
00701 break;
00702 case mdsFieldExtName:
00703 getExtName(pFsItem->szFilename, szField);
00704 break;
00705 case mdsFieldAuthor:
00706 case mdsFieldDescription:
00707 case mdsFieldFile:
00708 default:
00709 strcpy(szField, "");
00710 }
00711 CL_LOGPRINTF("%s", szField);
00712 }
00713
00714 static void mdsFetchFieldOfFolder(mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char*szField)
00715 {
00716 CL_LOGPRINTF("entry");
00717
00718 if (NULL == pFsItem || NULL == sort || NULL == szField)
00719 {
00720 CL_ERRORPRINTF("invalid arguments");
00721 return;
00722 }
00723 if (pFsItem->fit != mdsFitFolder)
00724 {
00725 CL_ERRORPRINTF("invalid arguments");
00726 return;
00727 }
00728
00729 switch (sort->ft)
00730 {
00731 case mdsFieldFsName:
00732 strcpy(szField, pFsItem->szFilename);
00733 break;
00734 case mdsFieldTitle:
00735 getFakeTitle(pFsItem->szFilename, szField);
00736 break;
00737 case mdsFieldDate:
00738 getDate(pFsItem->szFilename, szField);
00739 break;
00740 case mdsFieldSize:
00741 {
00742
00743
00744 int size = 0;
00745 g_snprintf(szField, ERMDS_MAX_FILENAME_SIZE, "%d", size);
00746 }
00747 break;
00748 case mdsFieldExtName:
00749 case mdsFieldAuthor:
00750 case mdsFieldDescription:
00751 case mdsFieldFile:
00752 default:
00753 strcpy(szField, "");
00754 }
00755 CL_LOGPRINTF("%s", szField);
00756 }
00757
00758 static void mdsFetchFieldOfContainer(mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char*szField)
00759 {
00760 CL_LOGPRINTF("entry");
00761
00762 char szManifestPath[ERMDS_MAX_FILENAME_SIZE];
00763
00764 if (NULL == pFsItem || NULL == sort || NULL == szField)
00765 {
00766 CL_ERRORPRINTF("invalid arguments");
00767 return;
00768 }
00769 if (mdsFitContainer != pFsItem->fit)
00770 {
00771 CL_ERRORPRINTF("invalid arguments");
00772 return;
00773 }
00774
00775
00776 if (mdsFieldDate == sort->ft || mdsFieldDescription == sort->ft
00777 || mdsFieldFile == sort->ft || mdsFieldTitle == sort->ft
00778 || mdsFieldSize == sort->ft)
00779 {
00780
00781 g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, pFsItem->szFilename);
00782 CL_LOGPRINTF("Calling erClXmlFetchField: %s, %d, ...", szManifestPath, (int) sort->ft);
00783 erClXmlFetchField(szManifestPath, sort->ft, szField);
00784 }
00785 else if (mdsFieldExtName == sort->ft)
00786 {
00787 char szStartPage[ERMDS_MAX_FILENAME_SIZE+1];
00788 char szStartPagePath[ERMDS_MAX_FILENAME_SIZE+1];
00789
00790 g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, pFsItem->szFilename);
00791 CL_LOGPRINTF("Calling erClXmlFetchField: %s, %d, ...", szManifestPath, (int) mdsFieldFile);
00792 erClXmlFetchField(szManifestPath, mdsFieldFile, szStartPage);
00793 g_snprintf(szStartPagePath, ERMDS_MAX_FILENAME_SIZE, "%s/%s", pFsItem->szFilename, szStartPage);
00794 getExtName(szStartPagePath, szField);
00795 }
00796 else
00797 {
00798 CL_LOGPRINTF("Field(%d) never be found in manifest.", (int)sort->ft);
00799 strcpy(szField, "");
00800 }
00801
00802 if (0 == strlen(szField))
00803 {
00804 switch (sort->ft)
00805 {
00806 case mdsFieldFsName:
00807 strcpy(szField, pFsItem->szFilename);
00808 break;
00809 case mdsFieldDate:
00810 getDate(pFsItem->szFilename, szField);
00811 break;
00812 case mdsFieldTitle:
00813 getFakeTitle(pFsItem->szFilename, szField);
00814 break;
00815 case mdsFieldSize:
00816 {
00817 int size = 0;
00818 size = getSize(pFsItem->szFilename);
00819 g_snprintf(szField, ERMDS_MAX_FILENAME_SIZE, "%d", size);
00820
00821 erClXmlSetFieldSize(pFsItem->szFilename, size);
00822 }
00823 break;
00824 default:
00825 CL_ERRORPRINTF("can't get the field value");
00826 }
00827 }
00828 CL_LOGPRINTF("Time of %s: %s", pFsItem->szFilename, szField);
00829 }
00830
00831
00832 static void mdsFetchFieldOfSymlink(mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char*szField)
00833 {
00834 CL_LOGPRINTF("entry");
00835
00836 char* cp = NULL;
00837 char szFilename[ERMDS_MAX_FILENAME_SIZE];
00838 char szRealpath[PATH_MAX];
00839 mdsFsItemType_e fit;
00840 mdsFsItem_t fsItem;
00841
00842 if (NULL == pFsItem || NULL == sort || NULL == szField)
00843 {
00844 CL_ERRORPRINTF("invalid arguments");
00845 return;
00846 }
00847 if (mdsFitSymlink != pFsItem->fit)
00848 {
00849 CL_ERRORPRINTF("invalid arguments");
00850 return;
00851 }
00852
00853 strcpy(szField, "");
00854
00855
00856 cp = realpath(pFsItem->szFilename, szRealpath);
00857 if (cp != NULL)
00858 {
00859 snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
00860
00861 erClGetSymlinkInfo(szFilename, &fit);
00862
00863 if (mdsFitFile == fit || mdsFitFolder == fit || mdsFitContainer == fit)
00864 {
00865
00866 fsItem.fit = fit;
00867 strcpy(fsItem.szFilename, szFilename);
00868 mdsFetchField(&fsItem, sort, szField);
00869 }
00870 else
00871 {
00872 CL_ERRORPRINTF("entry");
00873 }
00874 }
00875 else
00876 {
00877 CL_ERRORPRINTF("entry");
00878 }
00879
00880 CL_LOGPRINTF("entry");
00881 }
00882
00883 static void getFakeTitle(const char* szPath, char* szTitle)
00884 {
00885 char *pChar = NULL;
00886
00887 if (NULL == szPath || NULL == szTitle)
00888 {
00889 CL_ERRORPRINTF("invalid arguments");
00890 return;
00891 }
00892
00893 strcpy(szTitle, "");
00894
00895 if (strlen(szPath))
00896 {
00897
00898
00899 pChar = strrchr(szPath, (int) '.');
00900 if (pChar != NULL)
00901 {
00902 pChar++;
00903 if (extensionIsMobipocket(pChar))
00904 {
00905 if (getMobipocketTitle(szPath, szTitle))
00906 {
00907 return;
00908 }
00909 }
00910 }
00911
00912
00913 pChar = strrchr(szPath, (int) '/');
00914 if (pChar != NULL)
00915 {
00916 strcpy(szTitle, ++pChar);
00917 }
00918 else
00919 {
00920 CL_WARNPRINTF("Can not determine title of %s", szPath);
00921 }
00922 }
00923 else
00924 {
00925 CL_WARNPRINTF("Can not determine title of %s", szPath);
00926 }
00927 CL_LOGPRINTF("the title of %s is %s", szPath, szTitle);
00928 }
00929
00930
00931
00932
00933 static gboolean getMobipocketTitle(const char* szPath, char* szTitle)
00934 {
00935 GIOChannel *io;
00936 guint32 firstRecordIndex = 0;
00937 guint32 titleEncoding = 0;
00938 guint32 titleOffset = 0;
00939 guint32 titleLength = 0;
00940 guint32 check3Value = 0;
00941 int i;
00942 gchar *encoding = NULL;
00943 gchar *p;
00944 GString *tmpTitle;
00945 gunichar uniChar = 0;
00946 GIOStatus st;
00947
00948 gchar buf[9];
00949 memset(buf, '\0', sizeof(buf));
00950
00951 CL_LOGPRINTF("entry: [%s]", szPath);
00952
00953 io = g_io_channel_new_file(szPath, "r", NULL);
00954 if (io != NULL)
00955 {
00956 g_io_channel_set_encoding(io, NULL, NULL);
00957
00958
00959 st = g_io_channel_seek_position(io, MOBIPOCKET_CHECK1_OFFSET, G_SEEK_SET, NULL);
00960 if (st != G_IO_STATUS_NORMAL)
00961 {
00962 CL_ERRORPRINTF("Unable to seek to 0x%x", MOBIPOCKET_CHECK1_OFFSET);
00963 goto return_false;
00964 }
00965 g_io_channel_read_chars(io, buf, 8, NULL, NULL);
00966 buf[8] = '\0';
00967 if (strcmp(buf, "BOOKMOBI") != 0)
00968 {
00969 CL_ERRORPRINTF("Identifier 'BOOKMOBI' not found");
00970 if (strcmp(buf, "TEXtREAd") == 0)
00971 {
00972 CL_WARNPRINTF("Identifier 'TEXtREAd' found; Assuming PDB title is valid.");
00973
00974
00975 firstRecordIndex = 0;
00976 titleOffset = MOBIPOCKET_PDB_TITLE_OFFSET;
00977 titleLength = MOBIPOCKET_PDB_TITLE_LENGTH;
00978 encoding = g_strdup("UTF-8");
00979 goto read_title;
00980 }
00981 else
00982 {
00983 goto return_false;
00984 }
00985 }
00986 memset(buf, '\0', sizeof(buf));
00987
00988
00989 st = g_io_channel_seek_position(io, MOBIPOCKET_FIRST_RECORD, G_SEEK_SET, NULL);
00990 if (st != G_IO_STATUS_NORMAL)
00991 {
00992 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex);
00993 goto return_false;
00994 }
00995 g_io_channel_read_chars(io, buf, 4, NULL, NULL);
00996 for (i = 0; i < 4; i++)
00997 {
00998 firstRecordIndex = firstRecordIndex << 8;
00999 firstRecordIndex = firstRecordIndex + buf[i];
01000 }
01001 memset(buf, '\0', sizeof(buf));
01002
01003 CL_LOGPRINTF("firstRecordIndex = 0x%x", firstRecordIndex);
01004
01005
01006 st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_CHECK2_OFFSET, G_SEEK_SET, NULL);
01007 if (st != G_IO_STATUS_NORMAL)
01008 {
01009 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_CHECK2_OFFSET);
01010 goto return_false;
01011 }
01012 g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01013 buf[4] = '\0';
01014 if (strcmp(buf, "MOBI") != 0)
01015 {
01016 CL_ERRORPRINTF("Identifier 'MOBI' not found");
01017 goto return_false;
01018 }
01019 memset(buf, '\0', sizeof(buf));
01020
01021
01022 st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_ENCODING_OFFSET, G_SEEK_SET, NULL);
01023 if (st != G_IO_STATUS_NORMAL)
01024 {
01025 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_ENCODING_OFFSET);
01026 goto return_false;
01027 }
01028 g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01029 for (i = 0; i < 4; i++)
01030 {
01031 titleEncoding = titleEncoding << 8;
01032 titleEncoding = titleEncoding + buf[i];
01033 }
01034 if (titleEncoding == MOBIPOCKET_ENCODING_UTF8)
01035 {
01036 encoding = g_strdup("UTF-8");
01037 }
01038 else if (titleEncoding == MOBIPOCKET_ENCODING_WIN1252)
01039 {
01040 encoding = g_strdup("WINDOWS-1252");
01041 }
01042 else
01043 {
01044 CL_ERRORPRINTF("Unknown encoding 0x%x", titleEncoding);
01045 goto return_false;
01046 }
01047 memset(buf, '\0', sizeof(buf));
01048
01049
01050 st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_CHECK3_OFFSET, G_SEEK_SET, NULL);
01051 if (st != G_IO_STATUS_NORMAL)
01052 {
01053 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_CHECK3_OFFSET);
01054 goto return_false;
01055 }
01056 g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01057 for (i = 0; i < 4; i++)
01058 {
01059 check3Value = check3Value << 8;
01060 check3Value = check3Value + buf[i];
01061 }
01062 memset(buf, '\0', sizeof(buf));
01063
01064 if (check3Value < 2)
01065 {
01066
01067 CL_WARNPRINTF("Check 3: value < 2 ; fallback to PDB mode");
01068 firstRecordIndex = 0;
01069 titleOffset = MOBIPOCKET_PDB_TITLE_OFFSET;
01070 titleLength = MOBIPOCKET_PDB_TITLE_LENGTH;
01071 }
01072 else
01073 {
01074
01075
01076
01077 st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_TITLE_RECORD_OFFSET, G_SEEK_SET, NULL);
01078 if (st != G_IO_STATUS_NORMAL)
01079 {
01080 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_TITLE_RECORD_OFFSET);
01081 goto return_false;
01082 }
01083 g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01084 for (i = 0; i < 4; i++)
01085 {
01086 titleOffset = titleOffset << 8;
01087 titleOffset = titleOffset + buf[i];
01088 }
01089 memset(buf, '\0', sizeof(buf));
01090
01091
01092 st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_TITLE_LENGTH_OFFSET, G_SEEK_SET, NULL);
01093 if (st != G_IO_STATUS_NORMAL)
01094 {
01095 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_TITLE_LENGTH_OFFSET);
01096 goto return_false;
01097 }
01098 g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01099 for (i = 0; i < 4; i++)
01100 {
01101 titleLength = titleLength << 8;
01102 titleLength = titleLength + buf[i];
01103 }
01104 memset(buf, '\0', sizeof(buf));
01105
01106
01107 if (titleLength >= ERMDS_MAX_FILENAME_SIZE)
01108 {
01109 CL_ERRORPRINTF("titleLength %d >= %d; truncating...", titleLength, ERMDS_MAX_FILENAME_SIZE);
01110 titleLength = ERMDS_MAX_FILENAME_SIZE - 1;
01111 }
01112 else if (titleLength == 0)
01113 {
01114
01115
01116 CL_WARNPRINTF("titleLength == 0");
01117 firstRecordIndex = 0;
01118 titleOffset = MOBIPOCKET_PDB_TITLE_OFFSET;
01119 titleLength = MOBIPOCKET_PDB_TITLE_LENGTH;
01120 }
01121
01122 }
01123
01124 read_title:
01125
01126 CL_LOGPRINTF("titleLength = %d, titleOffset = 0x%x", titleLength, titleOffset);
01127
01128
01129 st = g_io_channel_seek_position(io, firstRecordIndex + titleOffset, G_SEEK_SET, NULL);
01130 if (st != G_IO_STATUS_NORMAL)
01131 {
01132 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + titleOffset);
01133 goto return_false;
01134 }
01135
01136
01137 st = g_io_channel_set_encoding(io, encoding, NULL);
01138 if (st != G_IO_STATUS_NORMAL)
01139 {
01140 CL_ERRORPRINTF("Unable to change channel encoding to %s", encoding);
01141 goto return_false;
01142 }
01143
01144 CL_LOGPRINTF("Channel encoding changed to %s", encoding);
01145
01146
01147 tmpTitle = g_string_sized_new(titleLength);
01148 for (i = 0; i < titleLength; i++)
01149 {
01150 st = g_io_channel_read_unichar(io, &uniChar, NULL);
01151 if (st != G_IO_STATUS_NORMAL)
01152 {
01153 CL_ERRORPRINTF("Unable to read char from pos %d", i);
01154 goto return_false;
01155 }
01156 g_string_append_unichar(tmpTitle, uniChar);
01157 }
01158 strcpy(szTitle, tmpTitle->str);
01159 g_string_free(tmpTitle, TRUE);
01160
01161
01162 while ((p = strstr(szTitle, "&")) != NULL)
01163 {
01164 strcpy(p + 1, p + 5);
01165 }
01166
01167 CL_LOGPRINTF("Found title [%s]", szTitle);
01168 }
01169 else
01170 {
01171 CL_ERRORPRINTF("Unable to open file [%s]", szPath);
01172 goto return_false;
01173 }
01174
01175
01176 if (encoding) g_free(encoding);
01177 g_io_channel_shutdown(io, FALSE, NULL);
01178 g_io_channel_unref(io);
01179 CL_LOGPRINTF("leave");
01180 return TRUE;
01181
01182 return_false:
01183 if (encoding) g_free(encoding);
01184 if (io)
01185 {
01186 g_io_channel_shutdown(io, FALSE, NULL);
01187 g_io_channel_unref(io);
01188 }
01189
01190 CL_WARNPRINTF("Not a valid Mobipocket file [%s]", szPath);
01191 return FALSE;
01192 }
01193
01194 static int getSize(const char * pathName)
01195 {
01196 struct stat statbuf;
01197
01198
01199 if (0 != stat(pathName, &statbuf))
01200 {
01201 return ERCL_INVALID_SIZE;
01202 }
01203
01204 if (S_ISREG(statbuf.st_mode))
01205 {
01206 int size = 0;
01207 size = statbuf.st_blocks * 512;
01208 CL_LOGPRINTF("the title of %s is %d", pathName, size);
01209 return statbuf.st_blocks * 512;
01210 }
01211
01212 if (S_ISDIR(statbuf.st_mode))
01213 {
01214
01215 DIR * dir = opendir(pathName);
01216 struct dirent *entry;
01217 int size = 0, item = 0;
01218 if (NULL == dir)
01219 {
01220 CL_WARNPRINTF("Open dir returns NULL");
01221 return size;
01222 }
01223 while ((entry = readdir(dir)) != NULL)
01224 {
01225 if (strcmp(".", entry->d_name) && strcmp("..", entry->d_name))
01226 {
01227 char path[ERMDS_MAX_FILENAME_SIZE] ={0};
01228 snprintf(path, ERMDS_MAX_FILENAME_SIZE, "%s/%s",
01229 pathName, entry->d_name);
01230 item = getSize(path);
01231 CL_LOGPRINTF("name: %s", path);
01232 if (ERCL_INVALID_SIZE != item)
01233 {
01234 size += item;
01235 }
01236 }
01237 }
01238 closedir(dir);
01239 CL_LOGPRINTF("the title of %s is %d", pathName, size);
01240 return size;
01241 }
01242 return ERCL_INVALID_SIZE;
01243 }
01244
01245
01246
01247
01248 static void getDate(const char *szPath, char *szDate)
01249 {
01250 struct stat statBuf;
01251
01252 if (NULL == szPath || NULL == szDate)
01253 {
01254 CL_ERRORPRINTF("invalid arguments");
01255 return;
01256 }
01257
01258 strcpy(szDate, "");
01259
01260 if (strlen(szPath))
01261 {
01262 if (stat(szPath, &statBuf) == 0)
01263 {
01264 if (S_ISREG(statBuf.st_mode) != 0 || S_ISDIR(statBuf.st_mode))
01265 {
01266
01267 struct tm localTime;
01268
01269 localtime_r(&statBuf.st_mtime, &localTime);
01270 strftime(szDate, ERCL_MAX_SUBTITLE_SIZE, "%Y-%m-%dT%H:%M:%S", &localTime);
01271 CL_LOGPRINTF("Time of %s: %s", szPath, szDate);
01272 }
01273 else if (S_ISLNK(statBuf.st_mode))
01274 {
01275 CL_WARNPRINTF("getDate of S_ISLNK not implemented yet.");
01276 }
01277 else
01278 {
01279 CL_WARNPRINTF("%s is not a regular file or directory", szPath);
01280 }
01281 }
01282 }
01283 else
01284 {
01285 CL_WARNPRINTF("Can't determinte the date of %s", szPath);
01286 }
01287 }
01288
01289 static void getExtName(const char*szPath, char*szExt)
01290 {
01291 struct stat statbuf;
01292 char *pChar = NULL;
01293 char *pTmp = NULL;
01294
01295 if (NULL == szPath || NULL == szExt)
01296 {
01297 CL_ERRORPRINTF("invalid arguments");
01298 return;
01299 }
01300
01301 strcpy(szExt, "");
01302
01303 if (strlen(szPath))
01304 {
01305
01306 if (0 != stat(szPath, &statbuf))
01307 {
01308 CL_WARNPRINTF("entry");
01309
01310 if (strstr(szPath, "dummy.bmp"))
01311 {
01312 strcpy(szExt, "bmp");
01313 }
01314 }
01315 else
01316 {
01317 if (S_ISREG(statbuf.st_mode))
01318 {
01319 pChar = strrchr(szPath, (int) '.');
01320 pTmp = strrchr(szPath, (int) '/');
01321
01322
01323
01324
01325
01326 if (pChar != NULL && (pTmp == NULL || pTmp < pChar))
01327 {
01328 strcpy(szExt, ++pChar);
01329 CL_LOGPRINTF("the extname of %s is %s", szPath, szExt);
01330 }
01331 else
01332 {
01333 CL_WARNPRINTF("%s does not have a file extension", szPath);
01334 }
01335 }
01336 else if(S_ISDIR(statbuf.st_mode))
01337 {
01338 CL_WARNPRINTF("%s is a directory", szPath);
01339 }
01340 else if(S_ISLNK(statbuf.st_mode))
01341 {
01342 CL_WARNPRINTF("%s is a symbollink", szPath);
01343 }
01344 else
01345 {
01346 CL_WARNPRINTF("entry");
01347 }
01348 }
01349 }
01350 else
01351 {
01352 CL_WARNPRINTF("%s does not have a file extension", szPath);
01353 }
01354
01355
01356 for (pChar = szExt ; *pChar ; pChar++)
01357 {
01358 *pChar = tolower(*pChar);
01359 }
01360 }
01361
01362
01363 static int erClGetFileType(const char *szPath)
01364 {
01365 struct stat statBuf;
01366 char * ext;
01367
01368
01369
01370
01371
01372
01373 ext = strrchr(szPath, '.');
01374 if (ext && strcasecmp(++ext, "mbp") == 0)
01375 {
01376 CL_LOGPRINTF("Ignoring [%s] because it has extension [%s]", szPath, ext);
01377 return GFT_IGNORE;
01378 }
01379
01380 if (lstat(szPath, &statBuf) == -1)
01381 {
01382 CL_ERRORPRINTF("lstat(%s) returned with error [%s]", szPath, strerror(errno));
01383 return GFT_NOSUCHFILE;
01384 }
01385 else
01386 {
01387 if (S_ISLNK(statBuf.st_mode))
01388 {
01389 return GFT_SYMLINK;
01390 }
01391 else if (S_ISDIR(statBuf.st_mode))
01392 {
01393 return GFT_DIR;
01394 }
01395 else
01396 {
01397 return GFT_FILE;
01398 }
01399 }
01400 }
01401
01402 static int erClGetSymlinkInfo(const char* szRealpath, mdsFsItemType_e* pFit)
01403 {
01404 int n;
01405 char szManifestPath[ERMDS_MAX_FILENAME_SIZE];
01406 struct stat statbuf;
01407 int filetype;
01408 int ret;
01409
01410
01411 ret = ERCL_NOMATCH;
01412 *pFit = mdsFitUndefined;
01413 g_assert(szRealpath != NULL);
01414
01415
01416 filetype = erClGetFileType(szRealpath);
01417 switch (filetype)
01418 {
01419 case GFT_FILE:
01420 *pFit = mdsFitFile;
01421 ret = ERCL_OK;
01422 break;
01423
01424 case GFT_DIR:
01425 *pFit = mdsFitFolder;
01426 ret = ERCL_OK;
01427
01428
01429 n = g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, szRealpath);
01430 if (n < ERMDS_MAX_FILENAME_SIZE)
01431 {
01432
01433 if ( stat(szManifestPath, &statbuf) == 0
01434 && S_ISREG(statbuf.st_mode) )
01435 {
01436 *pFit = mdsFitContainer;
01437 }
01438 }
01439 break;
01440
01441 default:
01442 CL_ERRORPRINTF("unexpected filetype [%d] for [%s]", filetype, szRealpath);
01443 ;
01444 }
01445
01446 return ret;
01447 }
01448
01449 int erClGetDisplayItems(GArray * contentItemArray, int nBegin, int *nChunk, clDisplayItem_t * displayItemArray)
01450 {
01451 int nEnd = 0;
01452 int i;
01453 int j;
01454 mdsFsItem_t* pFsItem;
01455
01456
01457 if (nBegin < 0 || nBegin >= contentItemArray->len)
01458 {
01459 return ERCL_INVALID_ARGS;
01460 }
01461 else if (*nChunk < 0)
01462 {
01463 return ERCL_INVALID_ARGS;
01464 }
01465
01466 nEnd = (contentItemArray->len - 1 <= nBegin + *nChunk - 1) ? contentItemArray->len - 1 : nBegin + *nChunk - 1;
01467 *nChunk = nEnd - nBegin + 1;
01468
01469
01470
01471 for (i = 0, j = nBegin; i < *nChunk; i++, j++)
01472 {
01473 pFsItem = &g_array_index(contentItemArray, mdsFsItem_t, j);
01474
01475
01476 displayItemSetDefault(&displayItemArray[i]);
01477
01478
01479 switch (pFsItem->fit)
01480 {
01481 case mdsFitFile:
01482 fileGetDisplayItem(pFsItem, &displayItemArray[i]);
01483 break;
01484
01485 case mdsFitContainer:
01486 containerGetDisplayItem(pFsItem, &displayItemArray[i]);
01487 break;
01488
01489 case mdsFitFolder:
01490 folderGetDisplayItem(pFsItem, &displayItemArray[i]);
01491 break;
01492
01493 case mdsFitSymlink:
01494 symlinkGetDisplayItem(pFsItem, &displayItemArray[i]);
01495 break;
01496
01497 case mdsFitStorage:
01498 case mdsFitApplication:
01499 case mdsFitManifestDirectory:
01500 default:
01501 CL_LOGPRINTF("No action required.");
01502 }
01503 }
01504
01505 return ERCL_OK;
01506 }
01507
01508 static void displayItemSetDefault(clDisplayItem_t *displayItem)
01509 {
01510 if (NULL == displayItem)
01511 {
01512 return;
01513 }
01514 displayItem->iconID = clUnknownIcon;
01515 strcpy(displayItem->clIconURL, "");
01516 strcpy(displayItem->szFileExt, "");
01517 strcpy(displayItem->szTitle, "");
01518 strcpy(displayItem->szSubTitle, "");
01519 strcpy(displayItem->szDate, "");
01520 strcpy(displayItem->szDescription, "");
01521 strcpy(displayItem->szFilename, "");
01522 strcpy(displayItem->szManifest, "");
01523 displayItem->size = ERCL_INVALID_SIZE;
01524 displayItem->fit = mdsFitUndefined;
01525 displayItem->modifyEnable.bDefault = TRUE;
01526 displayItem->modifyEnable.bDelete = TRUE;
01527 displayItem->modifyEnable.bScribble = TRUE;
01528 displayItem->modifyEnable.bTagging = TRUE;
01529 }
01530
01531 static void fileGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
01532 {
01533 char* cp = NULL;
01534 char szFilename[ERMDS_MAX_FILENAME_SIZE];
01535 char szRealpath[ERMDS_MAX_FILENAME_SIZE];
01536
01537
01538 if (NULL == pFsItem || pFsItem->fit != mdsFitFile || NULL == displayItem)
01539 {
01540 CL_ERRORPRINTF("invalid arguments");
01541 return;
01542 }
01543
01544
01545 cp = realpath(pFsItem->szFilename, szRealpath);
01546 if (cp != NULL)
01547 {
01548 CL_LOGPRINTF("entry %s", szRealpath);
01549 snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01550 }
01551 else
01552 {
01553 CL_ERRORPRINTF("entry %s", pFsItem->szFilename);
01554 strcpy(szFilename, pFsItem->szFilename);
01555 }
01556
01557
01558 strcpy(displayItem->szFilename, szFilename);
01559
01560 displayItem->fit = pFsItem->fit;
01561
01562 getFakeTitle(szFilename, displayItem->szTitle);
01563
01564 getExtName(szFilename, displayItem->szFileExt);
01565 if (0 == strlen(displayItem->szFileExt))
01566 {
01567 CL_WARNPRINTF("%s does not have a file extension", szFilename);
01568 }
01569
01570 getDate(szFilename, displayItem->szDate);
01571
01572 displayItem->size = getSize(szFilename);
01573 }
01574
01575 static void folderGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
01576 {
01577 char* cp = NULL;
01578 char szFilename[ERMDS_MAX_FILENAME_SIZE];
01579 char szRealpath[PATH_MAX];
01580
01581 if (pFsItem == NULL || pFsItem->fit != mdsFitFolder || displayItem == NULL)
01582 {
01583 CL_ERRORPRINTF("invalid arguments");
01584 return;
01585 }
01586
01587
01588 cp = realpath(pFsItem->szFilename, szRealpath);
01589 if (cp != NULL)
01590 {
01591 CL_LOGPRINTF("entry %s", szRealpath);
01592 snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01593 }
01594 else
01595 {
01596 CL_ERRORPRINTF("entry %s", pFsItem->szFilename);
01597 strcpy(szFilename, pFsItem->szFilename);
01598 }
01599
01600 strcpy(displayItem->szFilename, szFilename);
01601
01602 displayItem->fit = pFsItem->fit;
01603
01604 getFakeTitle(szFilename, displayItem->szTitle);
01605
01606 displayItem->iconID = clFolderIcon;
01607
01608 getDate(szFilename, displayItem->szDate);
01609
01610
01611
01612 }
01613
01614 static void containerGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
01615 {
01616 char* cp = NULL;
01617 char szFilename[ERMDS_MAX_FILENAME_SIZE];
01618 char szRealpath[PATH_MAX];
01619 char szManifestPath[ERMDS_MAX_FILENAME_SIZE];
01620 char storageDirName[ERMDS_MAX_FILENAME_SIZE];
01621 int nPathLength;
01622 int ret;
01623 struct stat statbuf;
01624 struct statfs statfsbuf;
01625 st_ContentType_e storageType;
01626 mdsFsItem_t fsItemSymlink;
01627
01628 static int nSymlinkChain = 0;
01629
01630 if (NULL == pFsItem || pFsItem->fit != mdsFitContainer || NULL == displayItem)
01631 {
01632 CL_ERRORPRINTF("invalid arguments");
01633 return;
01634 }
01635
01636
01637
01638 cp = realpath(pFsItem->szFilename, szRealpath);
01639 if (cp != NULL)
01640 {
01641 CL_LOGPRINTF("entry %s", szRealpath);
01642 snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01643 }
01644 else
01645 {
01646 CL_LOGPRINTF("entry %s", pFsItem->szFilename);
01647 strcpy(szFilename, pFsItem->szFilename);
01648 }
01649
01650
01651 displayItem->fit = pFsItem->fit;
01652
01653
01654 nPathLength = g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, szFilename);
01655 if ( stat(szManifestPath, &statbuf) == 0
01656 && S_ISREG(statbuf.st_mode) )
01657 {
01658
01659 strcpy(displayItem->szManifest, szManifestPath);
01660
01661
01662
01663 ret = erClXmlParseManifest(szFilename, displayItem);
01664
01665 if (ret == 0)
01666 {
01667 switch (displayItem->fit)
01668 {
01669 case mdsFitContainer:
01670
01671 getExtName(displayItem->szFilename, displayItem->szFileExt);
01672 if (0 == strlen(displayItem->szFileExt))
01673 {
01674 CL_WARNPRINTF("%s does not have a file extension", szFilename);
01675 }
01676 if (displayItem->size <= 0)
01677 {
01678
01679 displayItem->size = getSize(szFilename);
01680 erClXmlSetFieldSize(szFilename, displayItem->size);
01681 }
01682 break;
01683
01684 case mdsFitStorage:
01685
01686 storageType = ctrl_get_storageType(displayItem->szExtID);
01687 if ( stackIsStorage(storageType)
01688 && storageIsMounted(storageType)
01689 && mdsGetRootLocation(storageType, storageDirName, sizeof(storageDirName)) > 0 )
01690 {
01691 if (statfs(storageDirName, &statfsbuf) == 0)
01692 {
01693 displayItem->size = statfsbuf.f_bavail * statfsbuf.f_bsize / 1024;
01694 }
01695 }
01696 break;
01697
01698 case mdsFitManifestSymlinkLocale:
01699
01700 snprintf( szFilename, sizeof(szFilename),
01701 "%s/.%s",
01702 displayItem->szFilename,
01703 languagesGetLocale() );
01704 if ( stat(szFilename, &statbuf) == 0 )
01705 {
01706 strcpy(displayItem->szFilename, szFilename);
01707 }
01708 else
01709 {
01710 snprintf( szFilename, sizeof(szFilename),
01711 "%s/.%s",
01712 displayItem->szFilename,
01713 DEFAULT_LOCALE );
01714 if ( stat(szFilename, &statbuf) == 0 )
01715 {
01716 strcpy(displayItem->szFilename, szFilename);
01717 }
01718 else
01719 {
01720 CL_WARNPRINTF("not found [%s]", szFilename);
01721
01722 fsItemSymlink = *pFsItem;
01723 fsItemSymlink.fit = mdsFitFolder;
01724 strcpy(fsItemSymlink.szFilename, displayItem->szFilename);
01725 folderGetDisplayItem(&fsItemSymlink, displayItem);
01726 break;
01727 }
01728 }
01729
01730
01731 case mdsFitManifestSymlink:
01732 if (nSymlinkChain < ERMDS_MAX_SYMLINK_CHAIN)
01733 {
01734 nSymlinkChain++;
01735
01736 fsItemSymlink = *pFsItem;
01737 fsItemSymlink.fit = mdsFitSymlink;
01738 strcpy(fsItemSymlink.szFilename, displayItem->szFilename);
01739
01740 symlinkGetDisplayItem(&fsItemSymlink, displayItem);
01741 nSymlinkChain--;
01742 }
01743 else
01744 {
01745 CL_ERRORPRINTF("Symlink chain too long for [%s]", displayItem->szFilename);
01746 ret = -1;
01747 }
01748 break;
01749
01750 default:
01751 if (displayItem->iconID == clUnknownIcon)
01752 {
01753 displayItem->iconID = clFolderIcon;
01754 }
01755 }
01756 }
01757 else
01758 {
01759 CL_ERRORPRINTF("Failure to parse %s", szManifestPath);
01760 CL_ERRORPRINTF("Downgrading %s to folder", szFilename);
01761
01762 strcpy(displayItem->szFilename, szFilename);
01763
01764 displayItem->fit = mdsFitFolder;
01765
01766 displayItem->iconID = clFolderIcon;
01767
01768 getFakeTitle(szFilename, displayItem->szTitle);
01769 }
01770 }
01771 else
01772 {
01773
01774 CL_ERRORPRINTF("%s is missing. Illegal branch", szManifestPath);
01775 }
01776 }
01777
01778 static void symlinkGetDisplayItem(mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
01779 {
01780 char* cp = NULL;
01781 char szFilename[ERMDS_MAX_FILENAME_SIZE];
01782 char szRealpath[PATH_MAX];
01783 mdsFsItem_t fsItem;
01784 mdsFsItemType_e fit;
01785
01786 if (NULL == pFsItem || pFsItem->fit != mdsFitSymlink || NULL == displayItem)
01787 {
01788 CL_ERRORPRINTF("invalid arguments");
01789 return;
01790 }
01791
01792
01793
01794 cp = realpath(pFsItem->szFilename, szRealpath);
01795 if (cp != NULL)
01796 {
01797
01798 snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01799 erClGetSymlinkInfo(szFilename, &fit);
01800 displayItem->fit = fit;
01801
01802 fsItem.fit = fit;
01803 strcpy(fsItem.szFilename, szFilename);
01804 switch (fit)
01805 {
01806 case mdsFitContainer:
01807 containerGetDisplayItem(&fsItem, displayItem);
01808 break;
01809 case mdsFitFile:
01810 fileGetDisplayItem(&fsItem, displayItem);
01811 break;
01812 case mdsFitFolder:
01813 folderGetDisplayItem(&fsItem, displayItem);
01814 break;
01815 default:
01816 CL_ERRORPRINTF("entry");
01817 break;
01818 }
01819 }
01820 else
01821 {
01822 CL_ERRORPRINTF("realpath error on [%s]", pFsItem->szFilename);
01823 }
01824 }
01825