diff options
Diffstat (limited to 'src/bookmarks.c')
-rw-r--r-- | src/bookmarks.c | 111 |
1 files changed, 108 insertions, 3 deletions
diff --git a/src/bookmarks.c b/src/bookmarks.c index 72c5ad04..27909349 100644 --- a/src/bookmarks.c +++ b/src/bookmarks.c | |||
@@ -22,6 +22,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
22 | 22 | ||
23 | #include "bookmarks.h" | 23 | #include "bookmarks.h" |
24 | #include "visited.h" | 24 | #include "visited.h" |
25 | #include "gmrequest.h" | ||
25 | #include "app.h" | 26 | #include "app.h" |
26 | 27 | ||
27 | #include <the_Foundation/file.h> | 28 | #include <the_Foundation/file.h> |
@@ -82,9 +83,10 @@ static int cmpTitleAscending_Bookmark_(const iBookmark **a, const iBookmark **b) | |||
82 | static const char *fileName_Bookmarks_ = "bookmarks.txt"; | 83 | static const char *fileName_Bookmarks_ = "bookmarks.txt"; |
83 | 84 | ||
84 | struct Impl_Bookmarks { | 85 | struct Impl_Bookmarks { |
85 | iMutex *mtx; | 86 | iMutex * mtx; |
86 | int idEnum; | 87 | int idEnum; |
87 | iHash bookmarks; /* bookmark ID is the hash key */ | 88 | iHash bookmarks; /* bookmark ID is the hash key */ |
89 | iPtrArray remoteRequests; | ||
88 | }; | 90 | }; |
89 | 91 | ||
90 | iDefineTypeConstruction(Bookmarks) | 92 | iDefineTypeConstruction(Bookmarks) |
@@ -93,9 +95,15 @@ void init_Bookmarks(iBookmarks *d) { | |||
93 | d->mtx = new_Mutex(); | 95 | d->mtx = new_Mutex(); |
94 | d->idEnum = 0; | 96 | d->idEnum = 0; |
95 | init_Hash(&d->bookmarks); | 97 | init_Hash(&d->bookmarks); |
98 | init_PtrArray(&d->remoteRequests); | ||
96 | } | 99 | } |
97 | 100 | ||
98 | void deinit_Bookmarks(iBookmarks *d) { | 101 | void deinit_Bookmarks(iBookmarks *d) { |
102 | iForEach(PtrArray, i, &d->remoteRequests) { | ||
103 | cancel_GmRequest(i.ptr); | ||
104 | iRelease(i.ptr); | ||
105 | } | ||
106 | deinit_PtrArray(&d->remoteRequests); | ||
99 | clear_Bookmarks(d); | 107 | clear_Bookmarks(d); |
100 | deinit_Hash(&d->bookmarks); | 108 | deinit_Hash(&d->bookmarks); |
101 | delete_Mutex(d->mtx); | 109 | delete_Mutex(d->mtx); |
@@ -154,15 +162,23 @@ void load_Bookmarks(iBookmarks *d, const char *dirPath) { | |||
154 | } | 162 | } |
155 | } | 163 | } |
156 | iRelease(f); | 164 | iRelease(f); |
165 | fetchRemote_Bookmarks(d); | ||
157 | } | 166 | } |
158 | 167 | ||
159 | void save_Bookmarks(const iBookmarks *d, const char *dirPath) { | 168 | void save_Bookmarks(const iBookmarks *d, const char *dirPath) { |
160 | lock_Mutex(d->mtx); | 169 | lock_Mutex(d->mtx); |
170 | iRegExp *remotePattern = iClob(new_RegExp("\\bremote\\b", caseSensitive_RegExpOption)); | ||
161 | iFile *f = newCStr_File(concatPath_CStr(dirPath, fileName_Bookmarks_)); | 171 | iFile *f = newCStr_File(concatPath_CStr(dirPath, fileName_Bookmarks_)); |
162 | if (open_File(f, writeOnly_FileMode | text_FileMode)) { | 172 | if (open_File(f, writeOnly_FileMode | text_FileMode)) { |
163 | iString *str = collectNew_String(); | 173 | iString *str = collectNew_String(); |
164 | iConstForEach(Hash, i, &d->bookmarks) { | 174 | iConstForEach(Hash, i, &d->bookmarks) { |
165 | const iBookmark *bm = (const iBookmark *) i.value; | 175 | const iBookmark *bm = (const iBookmark *) i.value; |
176 | iRegExpMatch m; | ||
177 | init_RegExpMatch(&m); | ||
178 | if (matchString_RegExp(remotePattern, &bm->tags, &m)) { | ||
179 | /* Remote bookmarks are not saved. */ | ||
180 | continue; | ||
181 | } | ||
166 | format_String(str, | 182 | format_String(str, |
167 | "%08x %lf %s\n%s\n%s\n", | 183 | "%08x %lf %s\n%s\n%s\n", |
168 | bm->icon, | 184 | bm->icon, |
@@ -327,3 +343,92 @@ const iString *bookmarkListPage_Bookmarks(const iBookmarks *d, enum iBookmarkLis | |||
327 | } | 343 | } |
328 | return str; | 344 | return str; |
329 | } | 345 | } |
346 | |||
347 | static iBool isRemoteSource_Bookmark_(void *context, const iBookmark *d) { | ||
348 | iUnused(context); | ||
349 | return hasTag_Bookmark(d, "remotesource"); | ||
350 | } | ||
351 | |||
352 | void remoteRequestFinished_Bookmarks_(iBookmarks *d, iGmRequest *req) { | ||
353 | iUnused(d); | ||
354 | postCommandf_App("bookmarks.request.finished req:%p", req); | ||
355 | } | ||
356 | |||
357 | void requestFinished_Bookmarks(iBookmarks *d, iGmRequest *req) { | ||
358 | iBool found = iFalse; | ||
359 | iForEach(PtrArray, i, &d->remoteRequests) { | ||
360 | if (i.ptr == req) { | ||
361 | remove_PtrArrayIterator(&i); | ||
362 | found = iTrue; | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | iAssert(found); | ||
367 | /* Parse all links in the result. */ | ||
368 | if (isSuccess_GmStatusCode(status_GmRequest(req))) { | ||
369 | iTime now; | ||
370 | initCurrent_Time(&now); | ||
371 | iRegExp *linkPattern = new_RegExp("^=>\\s*([^\\s]+)\\s+(.*)", 0); | ||
372 | iString src; | ||
373 | const iString *remoteTag = collectNewCStr_String("remote"); | ||
374 | initBlock_String(&src, body_GmRequest(req)); | ||
375 | iRangecc srcLine = iNullRange; | ||
376 | while (nextSplit_Rangecc(range_String(&src), "\n", &srcLine)) { | ||
377 | iRangecc line = srcLine; | ||
378 | trimEnd_Rangecc(&line); | ||
379 | iRegExpMatch m; | ||
380 | init_RegExpMatch(&m); | ||
381 | if (matchRange_RegExp(linkPattern, line, &m)) { | ||
382 | const iRangecc url = capturedRange_RegExpMatch(&m, 1); | ||
383 | const iRangecc title = capturedRange_RegExpMatch(&m, 2); | ||
384 | iString * urlStr = newRange_String(url); | ||
385 | const iString *absUrl = absoluteUrl_String(url_GmRequest(req), urlStr); | ||
386 | if (!findUrl_Bookmarks(d, absUrl)) { | ||
387 | iString *titleStr = newRange_String(title); | ||
388 | add_Bookmarks(d, absUrl, titleStr, remoteTag, 0x2601 /* cloud */); | ||
389 | delete_String(titleStr); | ||
390 | } | ||
391 | delete_String(urlStr); | ||
392 | } | ||
393 | } | ||
394 | deinit_String(&src); | ||
395 | iRelease(linkPattern); | ||
396 | } | ||
397 | else { | ||
398 | /* TODO: Show error? */ | ||
399 | } | ||
400 | iRelease(req); | ||
401 | if (isEmpty_PtrArray(&d->remoteRequests)) { | ||
402 | postCommand_App("bookmarks.changed"); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | void fetchRemote_Bookmarks(iBookmarks *d) { | ||
407 | if (!isEmpty_PtrArray(&d->remoteRequests)) { | ||
408 | return; /* Already ongoing. */ | ||
409 | } | ||
410 | lock_Mutex(d->mtx); | ||
411 | /* Remove all current remote bookmarks. */ { | ||
412 | size_t numRemoved = 0; | ||
413 | iForEach(Hash, i, &d->bookmarks) { | ||
414 | iBookmark *bm = (iBookmark *) i.value; | ||
415 | if (hasTag_Bookmark(bm, "remote")) { | ||
416 | delete_Bookmark(bm); | ||
417 | remove_HashIterator(&i); | ||
418 | numRemoved++; | ||
419 | } | ||
420 | } | ||
421 | if (numRemoved) { | ||
422 | postCommand_App("bookmarks.changed"); | ||
423 | } | ||
424 | } | ||
425 | iConstForEach(PtrArray, i, list_Bookmarks(d, NULL, isRemoteSource_Bookmark_, NULL)) { | ||
426 | const iBookmark *bm = i.ptr; | ||
427 | iGmRequest *req = new_GmRequest(certs_App()); | ||
428 | pushBack_PtrArray(&d->remoteRequests, req); | ||
429 | setUrl_GmRequest(req, &bm->url); | ||
430 | iConnect(GmRequest, req, finished, req, remoteRequestFinished_Bookmarks_); | ||
431 | submit_GmRequest(req); | ||
432 | } | ||
433 | unlock_Mutex(d->mtx); | ||
434 | } | ||