summaryrefslogtreecommitdiff
path: root/src/bookmarks.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-12-19 10:26:23 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-12-19 10:26:23 +0200
commit3bde9d383a107760ee56ebc7f780154bfd3f3de7 (patch)
tree4703b0625c68a30be76251c5349659f3c9d14a21 /src/bookmarks.c
parent6e54b0b5449e607417b2bd5b68ac4292277bad4b (diff)
Remote bookmark sources
Bookmarks tagged "remotesource" are fetched and all links are treated as remote bookmarks. Remote bookmarks are not saved locally.
Diffstat (limited to 'src/bookmarks.c')
-rw-r--r--src/bookmarks.c111
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)
82static const char *fileName_Bookmarks_ = "bookmarks.txt"; 83static const char *fileName_Bookmarks_ = "bookmarks.txt";
83 84
84struct Impl_Bookmarks { 85struct 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
90iDefineTypeConstruction(Bookmarks) 92iDefineTypeConstruction(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
98void deinit_Bookmarks(iBookmarks *d) { 101void 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
159void save_Bookmarks(const iBookmarks *d, const char *dirPath) { 168void 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
347static iBool isRemoteSource_Bookmark_(void *context, const iBookmark *d) {
348 iUnused(context);
349 return hasTag_Bookmark(d, "remotesource");
350}
351
352void remoteRequestFinished_Bookmarks_(iBookmarks *d, iGmRequest *req) {
353 iUnused(d);
354 postCommandf_App("bookmarks.request.finished req:%p", req);
355}
356
357void 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
406void 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}