00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00026
00027
00028
00029
00030
00031
00032
00033 #include <stdio.h>
00034 #include <memory.h>
00035 #include <time.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <unistd.h>
00039 #include <sys/types.h>
00040 #include <dirent.h>
00041 #include <string.h>
00042 #include <strings.h>
00043 #include <errno.h>
00044
00045 #include <glib.h>
00046
00047 #include <liberregxml/erregapi.h>
00048 #include <libermanifest/ermanifest.h>
00049
00050 #include "contentListerLog.h"
00051 #include "stack.h"
00052 #include "history.h"
00053 #include "programManager.h"
00054 #include "regValue.h"
00055 #include "metadataStoreManager.h"
00056 #include "system.h"
00057
00058 #define NO_VIEWER_ACTIVE ""
00059
00060
00061 static clDisplayItem_t* g_history[ARCHIVE_TYPE_COUNT];
00062 static char* g_location[TOTAL_STACK_COUNT];
00063 static char g_activeViewer[ARCHIVE_TYPE_COUNT][UAID_MAX_SIZE];
00064
00065
00066 static clDisplayItem_t *hsCreateItem(regLastRead_t * content);
00067 static void hsCreateConvertItem(regLastRead_t * content, clDisplayItem_t * item);
00068 static void hsAddRecent(const clDisplayItem_t * item);
00069
00070 void hsInit(void)
00071 {
00072 int i;
00073 char buf[ERMDS_MAX_FILENAME_SIZE];
00074 regLastRead_t *theBooks = NULL;
00075 regLastRead_t *theNews = NULL;
00076 regLastRead_t *theDocs = NULL;
00077 regLastRead_t *theNotes = NULL;
00078
00079 CL_HISTORYPRINTF("");
00080
00081
00082 theBooks = erRegGetLastRead(BOOKS_CATEGORY);
00083 theNews = erRegGetLastRead(NEWSPAPERS_CATEGORY);
00084 theDocs = erRegGetLastRead(DOCUMENTS_CATEGORY);
00085 theNotes = erRegGetLastRead(NOTES_CATEGORY);
00086
00087 g_history[st_ContentTypeBooks] = hsCreateItem(theBooks);
00088 if (theBooks)
00089 {
00090 CL_HISTORYPRINTF("Found BOOKS_CATEGORY (loc %s)", theBooks->position);
00091 g_location[st_ContentTypeBooks] = g_strdup(theBooks->position);
00092 erRegFreeLastRead(theBooks);
00093 }
00094 strncpy(g_activeViewer[st_ContentTypeBooks], NO_VIEWER_ACTIVE, UAID_MAX_SIZE);
00095
00096 g_history[st_ContentTypeNews] = hsCreateItem(theNews);
00097 if (theNews)
00098 {
00099 CL_HISTORYPRINTF("Found NEWSPAPERS_CATEGORY (loc %s)", theNews->position);
00100 g_location[st_ContentTypeNews] = g_strdup(theNews->position);
00101 erRegFreeLastRead(theNews);
00102 }
00103 strncpy(g_activeViewer[st_ContentTypeNews], NO_VIEWER_ACTIVE, UAID_MAX_SIZE);
00104
00105 g_history[st_ContentTypeDocs] = hsCreateItem(theDocs);
00106 if (theDocs)
00107 {
00108 CL_HISTORYPRINTF("Found DOCUMENTS_CATEGORY (loc %s)", theDocs->position);
00109 g_location[st_ContentTypeDocs] = g_strdup(theDocs->position);
00110 erRegFreeLastRead(theDocs);
00111 }
00112 strncpy(g_activeViewer[st_ContentTypeDocs], NO_VIEWER_ACTIVE, UAID_MAX_SIZE);
00113
00114 g_history[st_ContentTypeNotes] = hsCreateItem(theNotes);
00115 if (theNotes)
00116 {
00117 CL_HISTORYPRINTF("Found NOTES_CATEGORY (loc %s)", theNotes->position);
00118 g_location[st_ContentTypeNotes] = g_strdup(theNotes->position);
00119 erRegFreeLastRead(theNotes);
00120 }
00121 strncpy(g_activeViewer[st_ContentTypeNotes], NO_VIEWER_ACTIVE, UAID_MAX_SIZE);
00122
00123
00124 i = mdsGetRootLocation(st_RecentDocuments, buf, sizeof(buf));
00125 if (i > 0)
00126 {
00127 g_location[st_RecentDocuments] = g_strdup(buf);
00128 }
00129 else
00130 {
00131 CL_ERRORPRINTF("mdsGetRootLocation(st_RecentDocuments) returns [%d]", i);
00132 }
00133 }
00134
00135
00136
00137 void hsDestroy(void)
00138 {
00139 int index;
00140 regLastRead_t *theLastRead = NULL;
00141
00142 CL_HISTORYPRINTF("");
00143
00144
00145 prepare_registry_write();
00146 CL_HISTORYPRINTF("Checked and loaded registry");
00147
00148 CL_HISTORYPRINTF("Store BOOKS_CATEGORY");
00149 theLastRead = g_new0(regLastRead_t, 1);
00150 hsCreateConvertItem(theLastRead, g_history[st_ContentTypeBooks]);
00151
00152 if (g_location[st_ContentTypeBooks])
00153 {
00154 theLastRead->position = g_strdup(g_location[st_ContentTypeBooks]);
00155 }
00156 else
00157 {
00158 theLastRead->position = g_strdup("");
00159 }
00160 erRegSetLastRead(BOOKS_CATEGORY, theLastRead);
00161 erRegFreeLastRead(theLastRead);
00162
00163 CL_HISTORYPRINTF("Store NEWSPAPERS_CATEGORY");
00164 theLastRead = g_new0(regLastRead_t, 1);
00165 hsCreateConvertItem(theLastRead, g_history[st_ContentTypeNews]);
00166
00167 if (g_location[st_ContentTypeNews])
00168 {
00169 theLastRead->position = g_strdup(g_location[st_ContentTypeNews]);
00170 }
00171 else
00172 {
00173 theLastRead->position = g_strdup("");
00174 }
00175 CL_HISTORYPRINTF("position %s", theLastRead->position);
00176 erRegSetLastRead(NEWSPAPERS_CATEGORY, theLastRead);
00177 erRegFreeLastRead(theLastRead);
00178
00179 CL_HISTORYPRINTF("Store DOCUMENTS_CATEGORY");
00180 theLastRead = g_new0(regLastRead_t, 1);
00181 hsCreateConvertItem(theLastRead, g_history[st_ContentTypeDocs]);
00182 CL_HISTORYPRINTF("position %s", theLastRead->position);
00183
00184 if (g_location[st_ContentTypeDocs])
00185 {
00186 theLastRead->position = g_strdup(g_location[st_ContentTypeDocs]);
00187 }
00188 else
00189 {
00190 theLastRead->position = g_strdup("");
00191 }
00192 CL_HISTORYPRINTF("position %s", theLastRead->position);
00193 erRegSetLastRead(DOCUMENTS_CATEGORY, theLastRead);
00194 erRegFreeLastRead(theLastRead);
00195
00196 CL_HISTORYPRINTF("Store NOTES_CATEGORY");
00197 theLastRead = g_new0(regLastRead_t, 1);
00198 hsCreateConvertItem(theLastRead, g_history[st_ContentTypeNotes]);
00199
00200 if (g_location[st_ContentTypeNotes])
00201 {
00202 theLastRead->position = g_strdup(g_location[st_ContentTypeNotes]);
00203 }
00204 else
00205 {
00206 theLastRead->position = g_strdup("");
00207 }
00208 CL_HISTORYPRINTF("position %s", theLastRead->position);
00209 erRegSetLastRead(NOTES_CATEGORY, theLastRead);
00210 erRegFreeLastRead(theLastRead);
00211
00212 do_registry_write();
00213 CL_HISTORYPRINTF("Stored registry");
00214
00215
00216 CL_HISTORYPRINTF("Free resources");
00217
00218 for (index = 0; index < ARCHIVE_TYPE_COUNT; index++)
00219 {
00220 if (g_history[index])
00221 {
00222 g_free(g_history[index]);
00223 g_history[index] = NULL;
00224 }
00225
00226 if (g_location[index])
00227 {
00228 g_free(g_location[index]);
00229 g_location[index] = NULL;
00230 }
00231 }
00232 }
00233
00234 void hsStoreItem(st_ContentType_e contentType, clDisplayItem_t * item)
00235 {
00236 CL_HISTORYPRINTF("contentType %d item 0x%x", contentType, (unsigned int) item);
00237
00238 if ((item) && (stackIsArchive(contentType)))
00239 {
00240 memcpy(g_history[contentType], item, sizeof(clDisplayItem_t));
00241 }
00242
00243 if (item)
00244 {
00245 if ( item->fit == mdsFitFile
00246 && strcasecmp(item->szFileExt, "png") == 0 )
00247 {
00248
00249 CL_WARNPRINTF("Notes template: file [%s] not added to recent documents", item->szFilename);
00250 }
00251 else
00252 {
00253 hsAddRecent(item);
00254 }
00255 }
00256 }
00257
00258 void hsGetItem(st_ContentType_e contentType, clDisplayItem_t * item)
00259 {
00260 CL_HISTORYPRINTF("contentType %d item 0x%x", contentType, (unsigned int) item);
00261
00262 if ((item) && (stackIsArchive(contentType)))
00263 {
00264 memcpy(item, g_history[contentType], sizeof(clDisplayItem_t));
00265 }
00266 }
00267
00268 gboolean hsSetLocation(st_ContentType_e contentType, char *location)
00269 {
00270 CL_HISTORYPRINTF("type %d - %s", contentType, location);
00271
00272 if (stackIsArchive(contentType))
00273 {
00274 if (g_location[contentType])
00275 {
00276 g_free(g_location[contentType]);
00277 g_location[contentType] = NULL;
00278 }
00279
00280 g_location[contentType] = g_strdup(location);
00281 }
00282
00283 return TRUE;
00284 }
00285
00286 char *hsGetLocation(st_ContentType_e contentType)
00287 {
00288 char *theLocation = NULL;
00289
00290 CL_HISTORYPRINTF("type %d", contentType);
00291
00292 if (stackIsArchive(contentType))
00293 {
00294 theLocation = g_strdup(g_location[contentType]);
00295 }
00296 return theLocation;
00297 }
00298
00299 gboolean hsRemoveLocation(st_ContentType_e contentType)
00300 {
00301 gboolean returnValue = FALSE;
00302
00303 if (stackIsArchive(contentType))
00304 {
00305 if (g_location[contentType])
00306 {
00307 g_free(g_location[contentType]);
00308 g_location[contentType] = NULL;
00309 returnValue = TRUE;
00310 }
00311 }
00312 return returnValue;
00313 }
00314
00315 void hsSetActiveViewer(st_ContentType_e contentType, char *viewerId)
00316 {
00317 int index;
00318
00319 CL_HISTORYPRINTF("contentType %d viewerId %s", contentType, viewerId);
00320
00321 for (index = 0; index < ARCHIVE_TYPE_COUNT; index++)
00322 {
00323 if (g_activeViewer[index] == viewerId)
00324 {
00325 strncpy(g_activeViewer[index], NO_VIEWER_ACTIVE, UAID_MAX_SIZE);
00326 }
00327 }
00328
00329 if (stackIsArchive(contentType))
00330 {
00331 strncpy(g_activeViewer[contentType], viewerId, UAID_MAX_SIZE);
00332 }
00333 }
00334
00335 char *hsGetActiveViewer(st_ContentType_e contentType)
00336 {
00337 char *viewerId = NULL;
00338
00339 if (stackIsArchive(contentType))
00340 {
00341 viewerId = g_activeViewer[contentType];
00342
00343 CL_HISTORYPRINTF("contentType %d viewerId %s", contentType, viewerId);
00344 }
00345 return viewerId;
00346 }
00347
00348 st_ContentType_e hsGetContentType(char *viewerId)
00349 {
00350 st_ContentType_e theType = st_ContentTypeUndefined;
00351 int index;
00352
00353 CL_HISTORYPRINTF("viewerId %s", viewerId);
00354
00355 for (index = 0; index < ARCHIVE_TYPE_COUNT; index++)
00356 {
00357 if (strncmp(g_activeViewer[index], viewerId, UAID_MAX_SIZE) == 0)
00358 {
00359 CL_HISTORYPRINTF("theType %d", index);
00360 theType = index;
00361 }
00362 }
00363 return theType;
00364 }
00365
00366 static clDisplayItem_t *hsCreateItem(regLastRead_t * content)
00367 {
00368 clDisplayItem_t *theItem = NULL;
00369
00370 theItem = g_new0(clDisplayItem_t, 1);
00371 if ((theItem) && (content))
00372 {
00373 g_snprintf(theItem->szFilename, ERMDS_MAX_FILENAME_SIZE, "%s", content->documentPath);
00374 g_snprintf(theItem->szFileExt, ERMDS_MAX_FILENAME_SIZE, "%s", content->extension );
00375 if ( content->manifestPath == NULL
00376 || content->manifestPath[0] == '\0' )
00377 {
00378 theItem->fit = mdsFitFile;
00379 strcpy(theItem->szManifest, "");
00380 }
00381 else
00382 {
00383 theItem->fit = mdsFitContainer;
00384 g_snprintf(theItem->szManifest, ERMDS_MAX_FILENAME_SIZE, "%s", content->manifestPath);
00385 }
00386 }
00387 return theItem;
00388 }
00389
00390 static void hsCreateConvertItem(regLastRead_t * content, clDisplayItem_t * theItem)
00391 {
00392 if ((content) && (theItem))
00393 {
00394 content->documentPath = g_strdup(theItem->szFilename);
00395 content->extension = g_strdup(theItem->szFileExt);
00396 content->manifestPath = g_strdup(theItem->szManifest);
00397 }
00398 }
00399
00400
00401
00402
00403 static gboolean isSymLink(const char *szPath)
00404 {
00405 struct stat statBuf;
00406
00407 if ( lstat(szPath, &statBuf) == 0
00408 && S_ISLNK(statBuf.st_mode) )
00409 {
00410 return TRUE;
00411 }
00412 else
00413 {
00414 return FALSE;
00415 }
00416 }
00417
00418
00419
00420 static void hsAddRecent(const clDisplayItem_t * item)
00421 {
00422 g_assert(item != NULL);
00423 CL_HISTORYPRINTF("Entry: filename [%s] fit [%d]", item->szFilename, item->fit);
00424 g_return_if_fail(item->fit == mdsFitFile || item->fit == mdsFitContainer);
00425
00426 int sequence;
00427 int err;
00428 int n;
00429 gboolean done;
00430 char *cp;
00431 char szTargetFile[ERMDS_MAX_FILENAME_SIZE] = "";
00432 char szLinkName[ERMDS_MAX_FILENAME_SIZE] = "";
00433 char szLinkTarget[ERMDS_MAX_FILENAME_SIZE] = "";
00434
00435 DIR *dirp;
00436 struct dirent *direntp;
00437 const char *linkdir = g_location[st_RecentDocuments];
00438
00439
00440
00441 switch (item->fit)
00442 {
00443 case mdsFitFile:
00444 snprintf(szLinkName, sizeof(szLinkName), item->szFilename);
00445 break;
00446
00447 case mdsFitContainer:
00448 snprintf(szLinkName, sizeof(szLinkName), item->szManifest);
00449
00450 cp = strrchr(szLinkName, '/');
00451 g_return_if_fail(cp != NULL);
00452 *cp = '\0';
00453 break;
00454
00455 default:
00456 break;
00457 }
00458
00459
00460 if ( realpath(szLinkName, szTargetFile) == NULL )
00461 {
00462 CL_ERRORPRINTF("Could not resolve path [%s] error [%s]", szLinkName, strerror(errno));
00463 return;
00464 }
00465 CL_HISTORYPRINTF("target [%s]", szTargetFile);
00466
00467
00468 if ((dirp = opendir(linkdir)) == NULL)
00469 {
00470 CL_ERRORPRINTF("Could not open directory [%s] error [%s].", linkdir, strerror(errno));
00471 }
00472 else
00473 {
00474 while ((direntp = readdir(dirp)) != NULL)
00475 {
00476
00477 snprintf(szLinkName, sizeof(szLinkName), "%s/%s", linkdir, direntp->d_name);
00478 if ( isSymLink(szLinkName) )
00479 {
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 n = readlink(szLinkName, szLinkTarget, sizeof(szLinkTarget) - 1);
00490 if (n > 0 && strncmp(szLinkTarget, szTargetFile, n) == 0)
00491 {
00492
00493 szLinkTarget[n] = '\0';
00494 CL_HISTORYPRINTF("Remove symlink [%s] -> [%s]", szLinkName, szLinkTarget);
00495 unlink(szLinkName);
00496 }
00497 }
00498 }
00499 closedir(dirp);
00500 }
00501
00502
00503 done = FALSE;
00504 for ( sequence = 0 ; !done && sequence <= 99 ; sequence++ )
00505 {
00506
00507 time_t t_time = time(NULL);
00508 struct tm* tm_time = localtime( &t_time );
00509 snprintf( szLinkName,
00510 ERMDS_MAX_FILENAME_SIZE,
00511 "%s/Link_%04d-%02d-%02dT%02d:%02d:%02d:%02d",
00512 linkdir,
00513 tm_time->tm_year + 1900,
00514 tm_time->tm_mon + 1,
00515 tm_time->tm_mday,
00516 tm_time->tm_hour,
00517 tm_time->tm_min,
00518 tm_time->tm_sec,
00519 sequence );
00520
00521
00522 if (symlink(szTargetFile, szLinkName) == 0)
00523 {
00524 CL_HISTORYPRINTF("Created symlink [%s] -> [%s]", szLinkName, szTargetFile);
00525 done = TRUE;
00526 }
00527 else
00528 {
00529 err = errno;
00530 CL_ERRORPRINTF("Error [%s] on create symlink [%s] -> [%s]", strerror(err), szLinkName, szTargetFile);
00531 if (err == EEXIST)
00532 {
00533 CL_ERRORPRINTF("[%s] already exists", szLinkName);
00534 }
00535 }
00536 }
00537
00538
00539 hsLimitSymlinks(linkdir, MAX_RECENT_ITEMS);
00540 }
00541
00542
00543
00544 void hsCleanupSymlinks(const char* szLinkDir)
00545 {
00546 g_assert(szLinkDir != NULL);
00547 CL_HISTORYPRINTF("Entry: directory [%s]", szLinkDir);
00548
00549 DIR* dirp;
00550 struct dirent* direntp;
00551 struct stat statBuf;
00552
00553 char szName[ERMDS_MAX_FILENAME_SIZE];
00554
00555
00556 if ((dirp = opendir(szLinkDir)) == NULL)
00557 {
00558 CL_ERRORPRINTF("Could not open directory %s (error %s).", szLinkDir, strerror(errno));
00559 return;
00560 }
00561 else
00562 {
00563 while ((direntp = readdir(dirp)) != NULL)
00564 {
00565 if ( strcmp(".", direntp->d_name) == 0
00566 || strcmp("..", direntp->d_name) == 0)
00567 {
00568
00569 continue;
00570 }
00571
00572 snprintf(szName, ERMDS_MAX_FILENAME_SIZE, "%s/%s", szLinkDir, direntp->d_name);
00573 if ( isSymLink(szName)
00574 && stat(szName, &statBuf) == -1 )
00575 {
00576
00577 CL_HISTORYPRINTF("Remove symlink [%s]", szName);
00578 unlink(szName);
00579 }
00580 }
00581
00582 closedir(dirp);
00583 }
00584 }
00585
00586
00587
00588 void hsLimitSymlinks(const char* szLinkDir, int maxItems)
00589 {
00590 int i;
00591 DIR* dirp;
00592 struct dirent* direntp;
00593
00594 typedef struct
00595 {
00596 char szName[ERMDS_MAX_FILENAME_SIZE];
00597 } linkInfo_t;
00598
00599 linkInfo_t* linkTable = alloca( sizeof(linkInfo_t) * (maxItems + 1) );
00600 linkInfo_t* linkOldest = NULL;
00601 linkInfo_t* linkCurrent = &linkTable[0];
00602 int linkNum = 0;
00603
00604 g_return_if_fail(linkTable != NULL);
00605
00606 if ((dirp = opendir(szLinkDir)) == NULL)
00607 {
00608 CL_ERRORPRINTF("Could not open directory %s (error %s).", szLinkDir, strerror(errno));
00609 return;
00610 }
00611 else
00612 {
00613 while ((direntp = readdir(dirp)) != NULL)
00614 {
00615 if ( strcmp(".", direntp->d_name) == 0
00616 || strcmp("..", direntp->d_name) == 0)
00617 {
00618
00619 continue;
00620 }
00621
00622 linkCurrent = &linkTable[linkNum];
00623 snprintf(linkCurrent->szName, ERMDS_MAX_FILENAME_SIZE, "%s/%s", szLinkDir, direntp->d_name);
00624
00625 if (linkNum < maxItems)
00626 {
00627
00628 linkNum++;
00629 if ( linkOldest == NULL
00630 || strcmp(linkCurrent->szName, linkOldest->szName) < 0)
00631 {
00632 linkOldest = linkCurrent;
00633 }
00634 }
00635 else if (strcmp(linkCurrent->szName, linkOldest->szName) < 0)
00636 {
00637
00638 CL_HISTORYPRINTF("Remove symlink [%s]", linkCurrent->szName);
00639 delete_fsitem(linkCurrent->szName);
00640 }
00641 else
00642 {
00643
00644 CL_HISTORYPRINTF("Remove symlink [%s]", linkOldest->szName);
00645 delete_fsitem(linkOldest->szName);
00646 *linkOldest = *linkCurrent;
00647
00648
00649 for ( i = 0, linkCurrent = &linkTable[0] ;
00650 i < linkNum ;
00651 i++, linkCurrent++ )
00652 {
00653 if (strcmp(linkCurrent->szName, linkOldest->szName) < 0)
00654 {
00655 linkOldest = linkCurrent;
00656 }
00657 }
00658 }
00659 }
00660
00661 closedir(dirp);
00662 }
00663 }
00664