summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-09-07 23:06:07 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-09-07 23:06:07 +0300
commit6145c27ad68f3f49bdc8e5c621ef7209edf81545 (patch)
treef721ccb1377209e0b4525521338ad3244380790b
parent320791c629e988f4634590aadf1bee5ee53d1785 (diff)
LookupWidget: Finding identities
-rw-r--r--src/gmcerts.c40
-rw-r--r--src/gmcerts.h3
-rw-r--r--src/ui/lookupwidget.c54
3 files changed, 80 insertions, 17 deletions
diff --git a/src/gmcerts.c b/src/gmcerts.c
index a39b303a..0dc52041 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -179,7 +179,7 @@ iDefineTypeConstruction(GmIdentity)
179/*-----------------------------------------------------------------------------------------------*/ 179/*-----------------------------------------------------------------------------------------------*/
180 180
181struct Impl_GmCerts { 181struct Impl_GmCerts {
182 iMutex mtx; 182 iMutex *mtx;
183 iString saveDir; 183 iString saveDir;
184 iStringHash *trusted; 184 iStringHash *trusted;
185 iPtrArray idents; 185 iPtrArray idents;
@@ -337,7 +337,7 @@ static void load_GmCerts_(iGmCerts *d) {
337} 337}
338 338
339void init_GmCerts(iGmCerts *d, const char *saveDir) { 339void init_GmCerts(iGmCerts *d, const char *saveDir) {
340 init_Mutex(&d->mtx); 340 d->mtx = new_Mutex();
341 initCStr_String(&d->saveDir, saveDir); 341 initCStr_String(&d->saveDir, saveDir);
342 d->trusted = new_StringHash(); 342 d->trusted = new_StringHash();
343 init_PtrArray(&d->idents); 343 init_PtrArray(&d->idents);
@@ -345,7 +345,7 @@ void init_GmCerts(iGmCerts *d, const char *saveDir) {
345} 345}
346 346
347void deinit_GmCerts(iGmCerts *d) { 347void deinit_GmCerts(iGmCerts *d) {
348 iGuardMutex(&d->mtx, { 348 iGuardMutex(d->mtx, {
349 saveIdentities_GmCerts_(d); 349 saveIdentities_GmCerts_(d);
350 iForEach(PtrArray, i, &d->idents) { 350 iForEach(PtrArray, i, &d->idents) {
351 delete_GmIdentity(i.ptr); 351 delete_GmIdentity(i.ptr);
@@ -354,7 +354,7 @@ void deinit_GmCerts(iGmCerts *d) {
354 iRelease(d->trusted); 354 iRelease(d->trusted);
355 deinit_String(&d->saveDir); 355 deinit_String(&d->saveDir);
356 }); 356 });
357 deinit_Mutex(&d->mtx); 357 delete_Mutex(d->mtx);
358} 358}
359 359
360iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) { 360iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *cert) {
@@ -372,7 +372,7 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
372 iDate until; 372 iDate until;
373 validUntil_TlsCertificate(cert, &until); 373 validUntil_TlsCertificate(cert, &until);
374 iBlock *fingerprint = fingerprint_TlsCertificate(cert); 374 iBlock *fingerprint = fingerprint_TlsCertificate(cert);
375 lock_Mutex(&d->mtx); 375 lock_Mutex(d->mtx);
376 iTrustEntry *trust = value_StringHash(d->trusted, key); 376 iTrustEntry *trust = value_StringHash(d->trusted, key);
377 if (trust) { 377 if (trust) {
378 /* We already have it, check if it matches the one we trust for this domain (if it's 378 /* We already have it, check if it matches the one we trust for this domain (if it's
@@ -382,7 +382,7 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
382 if (secondsSince_Time(&trust->validUntil, &now) > 0) { 382 if (secondsSince_Time(&trust->validUntil, &now) > 0) {
383 /* Trusted cert is still valid. */ 383 /* Trusted cert is still valid. */
384 const iBool isTrusted = cmp_Block(fingerprint, &trust->fingerprint) == 0; 384 const iBool isTrusted = cmp_Block(fingerprint, &trust->fingerprint) == 0;
385 unlock_Mutex(&d->mtx); 385 unlock_Mutex(d->mtx);
386 delete_Block(fingerprint); 386 delete_Block(fingerprint);
387 delete_String(key); 387 delete_String(key);
388 return isTrusted; 388 return isTrusted;
@@ -395,7 +395,7 @@ iBool checkTrust_GmCerts(iGmCerts *d, iRangecc domain, const iTlsCertificate *ce
395 insert_StringHash(d->trusted, key, iClob(new_TrustEntry(fingerprint, &until))); 395 insert_StringHash(d->trusted, key, iClob(new_TrustEntry(fingerprint, &until)));
396 } 396 }
397 save_GmCerts_(d); 397 save_GmCerts_(d);
398 unlock_Mutex(&d->mtx); 398 unlock_Mutex(d->mtx);
399 delete_Block(fingerprint); 399 delete_Block(fingerprint);
400 delete_String(key); 400 delete_String(key);
401 return iTrue; 401 return iTrue;
@@ -410,16 +410,21 @@ const iGmIdentity *constIdentity_GmCerts(const iGmCerts *d, unsigned int id) {
410} 410}
411 411
412const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) { 412const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) {
413 lock_Mutex(d->mtx);
414 const iGmIdentity *found = NULL;
413 iConstForEach(PtrArray, i, &d->idents) { 415 iConstForEach(PtrArray, i, &d->idents) {
414 const iGmIdentity *ident = i.ptr; 416 const iGmIdentity *ident = i.ptr;
415 iConstForEach(StringSet, j, ident->useUrls) { 417 iConstForEach(StringSet, j, ident->useUrls) {
416 const iString *used = j.value; 418 const iString *used = j.value;
417 if (startsWithCase_String(url, cstr_String(used))) { 419 if (startsWithCase_String(url, cstr_String(used))) {
418 return ident; 420 found = ident;
421 goto done;
419 } 422 }
420 } 423 }
421 } 424 }
422 return NULL; 425done:
426 unlock_Mutex(d->mtx);
427 return found;
423} 428}
424 429
425iGmIdentity *newIdentity_GmCerts(iGmCerts *d, int flags, iDate validUntil, const iString *commonName, 430iGmIdentity *newIdentity_GmCerts(iGmCerts *d, int flags, iDate validUntil, const iString *commonName,
@@ -454,7 +459,7 @@ iGmIdentity *newIdentity_GmCerts(iGmCerts *d, int flags, iDate validUntil, const
454 return NULL; 459 return NULL;
455 } 460 }
456 } 461 }
457 pushBack_PtrArray(&d->idents, id); 462 iGuardMutex(d->mtx, pushBack_PtrArray(&d->idents, id));
458 return id; 463 return id;
459} 464}
460 465
@@ -467,6 +472,7 @@ static const char *certPath_GmCerts_(const iGmCerts *d, const iGmIdentity *ident
467} 472}
468 473
469void deleteIdentity_GmCerts(iGmCerts *d, iGmIdentity *identity) { 474void deleteIdentity_GmCerts(iGmCerts *d, iGmIdentity *identity) {
475 lock_Mutex(d->mtx);
470 /* Only delete the files if we created them. */ 476 /* Only delete the files if we created them. */
471 const char *filename = certPath_GmCerts_(d, identity); 477 const char *filename = certPath_GmCerts_(d, identity);
472 if (filename) { 478 if (filename) {
@@ -475,6 +481,7 @@ void deleteIdentity_GmCerts(iGmCerts *d, iGmIdentity *identity) {
475 } 481 }
476 removeOne_PtrArray(&d->idents, identity); 482 removeOne_PtrArray(&d->idents, identity);
477 collect_GmIdentity(identity); 483 collect_GmIdentity(identity);
484 unlock_Mutex(d->mtx);
478} 485}
479 486
480const iString *certificatePath_GmCerts(const iGmCerts *d, const iGmIdentity *identity) { 487const iString *certificatePath_GmCerts(const iGmCerts *d, const iGmIdentity *identity) {
@@ -499,3 +506,16 @@ void signOut_GmCerts(iGmCerts *d, const iString *url) {
499 setUse_GmIdentity(i.ptr, url, iFalse); 506 setUse_GmIdentity(i.ptr, url, iFalse);
500 } 507 }
501} 508}
509
510const iPtrArray *listIdentities_GmCerts(const iGmCerts *d, iGmCertsIdentityFilterFunc filter,
511 void *context) {
512 iPtrArray *list = collectNew_PtrArray();
513 lock_Mutex(d->mtx);
514 iConstForEach(PtrArray, i, &d->idents) {
515 if (!filter || filter(context, i.ptr)) {
516 pushBack_PtrArray(list, i.ptr);
517 }
518 }
519 unlock_Mutex(d->mtx);
520 return list;
521}
diff --git a/src/gmcerts.h b/src/gmcerts.h
index 92a12a6a..2ab4396e 100644
--- a/src/gmcerts.h
+++ b/src/gmcerts.h
@@ -57,6 +57,8 @@ const iString *name_GmIdentity(const iGmIdentity *);
57iDeclareType(GmCerts) 57iDeclareType(GmCerts)
58iDeclareTypeConstructionArgs(GmCerts, const char *saveDir) 58iDeclareTypeConstructionArgs(GmCerts, const char *saveDir)
59 59
60typedef iBool (*iGmCertsIdentityFilterFunc)(void *context, const iGmIdentity *);
61
60iBool checkTrust_GmCerts (iGmCerts *, iRangecc domain, const iTlsCertificate *cert); 62iBool checkTrust_GmCerts (iGmCerts *, iRangecc domain, const iTlsCertificate *cert);
61 63
62/** 64/**
@@ -83,6 +85,7 @@ iGmIdentity * identity_GmCerts (iGmCerts *, unsigned int id);
83const iGmIdentity * constIdentity_GmCerts (const iGmCerts *, unsigned int id); 85const iGmIdentity * constIdentity_GmCerts (const iGmCerts *, unsigned int id);
84const iGmIdentity * identityForUrl_GmCerts (const iGmCerts *, const iString *url); 86const iGmIdentity * identityForUrl_GmCerts (const iGmCerts *, const iString *url);
85const iPtrArray * identities_GmCerts (const iGmCerts *); 87const iPtrArray * identities_GmCerts (const iGmCerts *);
88const iPtrArray * listIdentities_GmCerts (const iGmCerts *, iGmCertsIdentityFilterFunc filter, void *context);
86 89
87void signIn_GmCerts (iGmCerts *, iGmIdentity *identity, const iString *url); 90void signIn_GmCerts (iGmCerts *, iGmIdentity *identity, const iString *url);
88void signOut_GmCerts (iGmCerts *, const iString *url); 91void signOut_GmCerts (iGmCerts *, const iString *url);
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c
index 5fcbaacd..dbe734bf 100644
--- a/src/ui/lookupwidget.c
+++ b/src/ui/lookupwidget.c
@@ -21,17 +21,19 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22 22
23#include "lookupwidget.h" 23#include "lookupwidget.h"
24
25#include "app.h"
26#include "bookmarks.h"
27#include "command.h"
24#include "documentwidget.h" 28#include "documentwidget.h"
25#include "lookup.h" 29#include "gmcerts.h"
26#include "listwidget.h" 30#include "gmutil.h"
31#include "history.h"
27#include "inputwidget.h" 32#include "inputwidget.h"
33#include "listwidget.h"
34#include "lookup.h"
28#include "util.h" 35#include "util.h"
29#include "command.h"
30#include "bookmarks.h"
31#include "history.h"
32#include "visited.h" 36#include "visited.h"
33#include "gmutil.h"
34#include "app.h"
35 37
36#include <the_Foundation/mutex.h> 38#include <the_Foundation/mutex.h>
37#include <the_Foundation/thread.h> 39#include <the_Foundation/thread.h>
@@ -156,6 +158,14 @@ static float bookmarkRelevance_LookupJob_(const iLookupJob *d, const iBookmark *
156 return h + iMax(p, t) + 2 * g; /* extra weight for tags */ 158 return h + iMax(p, t) + 2 * g; /* extra weight for tags */
157} 159}
158 160
161static float identityRelevance_LookupJob_(const iLookupJob *d, const iGmIdentity *identity) {
162 iString *cn = subject_TlsCertificate(identity->cert);
163 const float c = scoreMatch_(d->term, range_String(cn));
164 const float n = scoreMatch_(d->term, range_String(&identity->notes));
165 delete_String(cn);
166 return c + 2 * n; /* extra weight for notes */
167}
168
159static float visitedRelevance_LookupJob_(const iLookupJob *d, const iVisitedUrl *vis) { 169static float visitedRelevance_LookupJob_(const iLookupJob *d, const iVisitedUrl *vis) {
160 iUrl parts; 170 iUrl parts;
161 init_Url(&parts, &vis->url); 171 init_Url(&parts, &vis->url);
@@ -169,6 +179,10 @@ static iBool matchBookmark_LookupJob_(void *context, const iBookmark *bm) {
169 return bookmarkRelevance_LookupJob_(context, bm) > 0; 179 return bookmarkRelevance_LookupJob_(context, bm) > 0;
170} 180}
171 181
182static iBool matchIdentity_LookupJob_(void *context, const iGmIdentity *identity) {
183 return identityRelevance_LookupJob_(context, identity) > 0;
184}
185
172static void searchBookmarks_LookupJob_(iLookupJob *d) { 186static void searchBookmarks_LookupJob_(iLookupJob *d) {
173 /* Note: Called in a background thread. */ 187 /* Note: Called in a background thread. */
174 /* TODO: Thread safety! What if a bookmark gets deleted while its being accessed here? */ 188 /* TODO: Thread safety! What if a bookmark gets deleted while its being accessed here? */
@@ -230,6 +244,25 @@ static void searchHistory_LookupJob_(iLookupJob *d) {
230 } 244 }
231} 245}
232 246
247static void searchIdentities_LookupJob_(iLookupJob *d) {
248 /* Note: Called in a background thread. */
249 iConstForEach(PtrArray, i, listIdentities_GmCerts(certs_App(), matchIdentity_LookupJob_, d)) {
250 const iGmIdentity *identity = i.ptr;
251 iLookupResult *res = new_LookupResult();
252 res->type = identity_LookupResultType;
253 res->relevance = identityRelevance_LookupJob_(d, identity);
254 appendChar_String(&res->label, identity->icon);
255 appendChar_String(&res->label, ' ');
256 iString *cn = subject_TlsCertificate(identity->cert);
257 append_String(&res->label, cn);
258 delete_String(cn);
259 set_String(&res->meta,
260 collect_String(
261 hexEncode_Block(collect_Block(fingerprint_TlsCertificate(identity->cert)))));
262 pushBack_PtrArray(&d->results, res);
263 }
264}
265
233static iThreadResult worker_LookupWidget_(iThread *thread) { 266static iThreadResult worker_LookupWidget_(iThread *thread) {
234 iLookupWidget *d = userData_Thread(thread); 267 iLookupWidget *d = userData_Thread(thread);
235 printf("[LookupWidget] worker is running\n"); fflush(stdout); 268 printf("[LookupWidget] worker is running\n"); fflush(stdout);
@@ -271,6 +304,7 @@ static iThreadResult worker_LookupWidget_(iThread *thread) {
271 if (termLen >= 3) { 304 if (termLen >= 3) {
272 searchHistory_LookupJob_(job); 305 searchHistory_LookupJob_(job);
273 } 306 }
307 searchIdentities_LookupJob_(job);
274 } 308 }
275 /* Submit the result. */ 309 /* Submit the result. */
276 lock_Mutex(d->mtx); 310 lock_Mutex(d->mtx);
@@ -433,6 +467,12 @@ static void presentResults_LookupWidget_(iLookupWidget *d) {
433 format_String(&item->command, "open url:%s", cstr_String(&res->url)); 467 format_String(&item->command, "open url:%s", cstr_String(&res->url));
434 break; 468 break;
435 } 469 }
470 case identity_LookupResultType: {
471 item->fg = uiText_ColorId;
472 item->font = uiContent_FontId;
473 format_String(&item->text, "%s", cstr_String(&res->label));
474 break;
475 }
436 } 476 }
437 addItem_ListWidget(d->list, item); 477 addItem_ListWidget(d->list, item);
438 iRelease(item); 478 iRelease(item);