summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-05-21 08:30:39 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-05-21 08:30:39 +0300
commit911a56b56c4f9ec5d0c4f1fd15189102bc97fcdb (patch)
treed8a6cb36c6a7cacad9cd1b8c94755f3f974084e4
parent548034e167bd94d21ef9bcc2e6d2d8cbfaeb3d06 (diff)
Added identity exporting
Exporting an identity will display it in a new tab in PEM encoded format, where it can be saved or copied. IssueID #236
-rw-r--r--po/en.po4
-rw-r--r--res/lang/de.binbin20410 -> 20430 bytes
-rw-r--r--res/lang/en.binbin19158 -> 19153 bytes
-rw-r--r--res/lang/es.binbin21126 -> 21146 bytes
-rw-r--r--res/lang/fi.binbin21100 -> 21120 bytes
-rw-r--r--res/lang/fr.binbin21616 -> 21636 bytes
-rw-r--r--res/lang/ia.binbin21317 -> 21337 bytes
-rw-r--r--res/lang/ie.binbin20488 -> 20508 bytes
-rw-r--r--res/lang/pl.binbin22121 -> 22141 bytes
-rw-r--r--res/lang/ru.binbin32199 -> 32219 bytes
-rw-r--r--res/lang/sr.binbin30778 -> 30798 bytes
-rw-r--r--res/lang/tok.binbin19522 -> 19542 bytes
-rw-r--r--res/lang/zh_Hans.binbin18281 -> 18301 bytes
-rw-r--r--res/lang/zh_Hant.binbin18355 -> 18375 bytes
-rw-r--r--src/defs.h1
-rw-r--r--src/gmcerts.c6
-rw-r--r--src/gmutil.c3
-rw-r--r--src/history.c5
-rw-r--r--src/ui/documentwidget.c81
-rw-r--r--src/ui/documentwidget.h1
-rw-r--r--src/ui/root.c5
-rw-r--r--src/ui/sidebarwidget.c32
22 files changed, 92 insertions, 46 deletions
diff --git a/po/en.po b/po/en.po
index ef236ba8..440d074f 100644
--- a/po/en.po
+++ b/po/en.po
@@ -542,8 +542,8 @@ msgstr "Stop Using on This Page"
542msgid "ident.stopuse.all" 542msgid "ident.stopuse.all"
543msgstr "Stop Using Everywhere" 543msgstr "Stop Using Everywhere"
544 544
545msgid "ident.showuse" 545msgid "ident.export"
546msgstr "Show Usage" 546msgstr "Export"
547 547
548msgid "heading.ident.use" 548msgid "heading.ident.use"
549msgstr "IDENTITY USAGE" 549msgstr "IDENTITY USAGE"
diff --git a/res/lang/de.bin b/res/lang/de.bin
index e6b0de88..59bde344 100644
--- a/res/lang/de.bin
+++ b/res/lang/de.bin
Binary files differ
diff --git a/res/lang/en.bin b/res/lang/en.bin
index dfc4039c..a8093411 100644
--- a/res/lang/en.bin
+++ b/res/lang/en.bin
Binary files differ
diff --git a/res/lang/es.bin b/res/lang/es.bin
index e8543648..c582efdc 100644
--- a/res/lang/es.bin
+++ b/res/lang/es.bin
Binary files differ
diff --git a/res/lang/fi.bin b/res/lang/fi.bin
index 478c20ff..1e155087 100644
--- a/res/lang/fi.bin
+++ b/res/lang/fi.bin
Binary files differ
diff --git a/res/lang/fr.bin b/res/lang/fr.bin
index dbad1af7..1a88c420 100644
--- a/res/lang/fr.bin
+++ b/res/lang/fr.bin
Binary files differ
diff --git a/res/lang/ia.bin b/res/lang/ia.bin
index 3c72164f..c5800ec2 100644
--- a/res/lang/ia.bin
+++ b/res/lang/ia.bin
Binary files differ
diff --git a/res/lang/ie.bin b/res/lang/ie.bin
index b5bbe210..0b4d5414 100644
--- a/res/lang/ie.bin
+++ b/res/lang/ie.bin
Binary files differ
diff --git a/res/lang/pl.bin b/res/lang/pl.bin
index ea38c272..48f16b05 100644
--- a/res/lang/pl.bin
+++ b/res/lang/pl.bin
Binary files differ
diff --git a/res/lang/ru.bin b/res/lang/ru.bin
index 73db27d2..48a9c7d8 100644
--- a/res/lang/ru.bin
+++ b/res/lang/ru.bin
Binary files differ
diff --git a/res/lang/sr.bin b/res/lang/sr.bin
index 1333959d..111528b5 100644
--- a/res/lang/sr.bin
+++ b/res/lang/sr.bin
Binary files differ
diff --git a/res/lang/tok.bin b/res/lang/tok.bin
index b3d94d03..d06b4356 100644
--- a/res/lang/tok.bin
+++ b/res/lang/tok.bin
Binary files differ
diff --git a/res/lang/zh_Hans.bin b/res/lang/zh_Hans.bin
index 9a470421..27c269f6 100644
--- a/res/lang/zh_Hans.bin
+++ b/res/lang/zh_Hans.bin
Binary files differ
diff --git a/res/lang/zh_Hant.bin b/res/lang/zh_Hant.bin
index 27f84c64..e78942bf 100644
--- a/res/lang/zh_Hant.bin
+++ b/res/lang/zh_Hant.bin
Binary files differ
diff --git a/src/defs.h b/src/defs.h
index 71719f7a..650f7e65 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -56,6 +56,7 @@ enum iFileVersion {
56#define whiteStar_Icon "\u2606" 56#define whiteStar_Icon "\u2606"
57#define person_Icon "\U0001f464" 57#define person_Icon "\U0001f464"
58#define download_Icon "\u2ba7" 58#define download_Icon "\u2ba7"
59#define export_Icon "\U0001f4e4"
59#define hourglass_Icon "\u231b" 60#define hourglass_Icon "\u231b"
60#define timer_Icon "\u23f2" 61#define timer_Icon "\u23f2"
61#define home_Icon "\U0001f3e0" 62#define home_Icon "\U0001f3e0"
diff --git a/src/gmcerts.c b/src/gmcerts.c
index bf0f3924..8577cf2b 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -201,7 +201,11 @@ void clearUse_GmIdentity(iGmIdentity *d) {
201} 201}
202 202
203const iString *name_GmIdentity(const iGmIdentity *d) { 203const iString *name_GmIdentity(const iGmIdentity *d) {
204 return collect_String(subject_TlsCertificate(d->cert)); 204 iString *name = collect_String(subject_TlsCertificate(d->cert));
205 if (startsWith_String(name, "CN = ")) {
206 remove_Block(&name->chars, 0, 5);
207 }
208 return name;
205} 209}
206 210
207iDefineTypeConstruction(GmIdentity) 211iDefineTypeConstruction(GmIdentity)
diff --git a/src/gmutil.c b/src/gmutil.c
index 718a0a9a..2c9ba4eb 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -475,6 +475,9 @@ const char *mediaType_Path(const iString *path) {
475 endsWithCase_String(path, ".hpp")) { 475 endsWithCase_String(path, ".hpp")) {
476 return "text/plain"; 476 return "text/plain";
477 } 477 }
478 else if (endsWithCase_String(path, ".pem")) {
479 return "application/x-pem-file";
480 }
478 else if (endsWithCase_String(path, ".zip")) { 481 else if (endsWithCase_String(path, ".zip")) {
479 return "application/zip"; 482 return "application/zip";
480 } 483 }
diff --git a/src/history.c b/src/history.c
index 9f4e415b..ed8e6725 100644
--- a/src/history.c
+++ b/src/history.c
@@ -243,7 +243,7 @@ void add_History(iHistory *d, const iString *url ){
243 243
244iBool goBack_History(iHistory *d) { 244iBool goBack_History(iHistory *d) {
245 lock_Mutex(d->mtx); 245 lock_Mutex(d->mtx);
246 if (d->recentPos < size_Array(&d->recent) - 1) { 246 if (!isEmpty_Array(&d->recent) && d->recentPos < size_Array(&d->recent) - 1) {
247 d->recentPos++; 247 d->recentPos++;
248 postCommandf_Root(get_Root(), 248 postCommandf_Root(get_Root(),
249 "open history:1 scroll:%f url:%s", 249 "open history:1 scroll:%f url:%s",
@@ -279,7 +279,8 @@ iBool atLatest_History(const iHistory *d) {
279 279
280iBool atOldest_History(const iHistory *d) { 280iBool atOldest_History(const iHistory *d) {
281 iBool isOldest; 281 iBool isOldest;
282 iGuardMutex(d->mtx, isOldest = (d->recentPos == size_Array(&d->recent) - 1)); 282 iGuardMutex(d->mtx, isOldest = (isEmpty_Array(&d->recent) ||
283 d->recentPos == size_Array(&d->recent) - 1));
283 return isOldest; 284 return isOldest;
284} 285}
285 286
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 452e5508..337e2a03 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -976,7 +976,7 @@ iBool isPinned_DocumentWidget_(const iDocumentWidget *d) {
976 976
977static void showOrHidePinningIndicator_DocumentWidget_(iDocumentWidget *d) { 977static void showOrHidePinningIndicator_DocumentWidget_(iDocumentWidget *d) {
978 iWidget *w = as_Widget(d); 978 iWidget *w = as_Widget(d);
979 showCollapsed_Widget(findChild_Widget(root_Widget(as_Widget(d)), "document.pinned"), 979 showCollapsed_Widget(findChild_Widget(root_Widget(w), "document.pinned"),
980 isPinned_DocumentWidget_(d)); 980 isPinned_DocumentWidget_(d));
981} 981}
982 982
@@ -1214,7 +1214,9 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
1214 setRange_String(&d->sourceMime, param); 1214 setRange_String(&d->sourceMime, param);
1215 } 1215 }
1216 else if (startsWith_Rangecc(param, "text/") || 1216 else if (startsWith_Rangecc(param, "text/") ||
1217 equal_Rangecc(param, "application/json")) { 1217 equal_Rangecc(param, "application/json") ||
1218 equal_Rangecc(param, "application/x-pem-file") ||
1219 equal_Rangecc(param, "application/pem-certificate-chain")) {
1218 docFormat = plainText_GmDocumentFormat; 1220 docFormat = plainText_GmDocumentFormat;
1219 setRange_String(&d->sourceMime, param); 1221 setRange_String(&d->sourceMime, param);
1220 } 1222 }
@@ -1383,37 +1385,42 @@ static void cacheDocumentGlyphs_DocumentWidget_(const iDocumentWidget *d) {
1383 } 1385 }
1384} 1386}
1385 1387
1388static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float normScrollY,
1389 const iGmResponse *resp) {
1390 setLinkNumberMode_DocumentWidget_(d, iFalse);
1391 clear_ObjectList(d->media);
1392 delete_Gempub(d->sourceGempub);
1393 d->sourceGempub = NULL;
1394 reset_GmDocument(d->doc);
1395 resetWideRuns_DocumentWidget_(d);
1396 d->state = fetching_RequestState;
1397 /* Do the fetch. */ {
1398 d->initNormScrollY = normScrollY;
1399 /* Use the cached response data. */
1400 updateTrust_DocumentWidget_(d, resp);
1401 d->sourceTime = resp->when;
1402 d->sourceStatus = success_GmStatusCode;
1403 format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached"));
1404 set_Block(&d->sourceContent, &resp->body);
1405 updateDocument_DocumentWidget_(d, resp, iTrue);
1406 postProcessRequestContent_DocumentWidget_(d, iTrue);
1407 }
1408 d->state = ready_RequestState;
1409 init_Anim(&d->altTextOpacity, 0);
1410 reset_SmoothScroll(&d->scrollY);
1411 init_Anim(&d->scrollY.pos, d->initNormScrollY * size_GmDocument(d->doc).y);
1412 updateSideOpacity_DocumentWidget_(d, iFalse);
1413 updateVisible_DocumentWidget_(d);
1414 moveSpan_SmoothScroll(&d->scrollY, 0, 0); /* clamp position to new max */
1415 cacheDocumentGlyphs_DocumentWidget_(d);
1416 d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag;
1417 postCommandf_Root(as_Widget(d)->root, "document.changed doc:%p url:%s", d, cstr_String(d->mod.url));
1418}
1419
1386static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { 1420static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) {
1387 const iRecentUrl *recent = findUrl_History(d->mod.history, d->mod.url); 1421 const iRecentUrl *recent = findUrl_History(d->mod.history, d->mod.url);
1388 if (recent && recent->cachedResponse) { 1422 if (recent && recent->cachedResponse) {
1389 const iGmResponse *resp = recent->cachedResponse; 1423 updateFromCachedResponse_DocumentWidget_(d, recent->normScrollY, recent->cachedResponse);
1390 clear_ObjectList(d->media);
1391 delete_Gempub(d->sourceGempub);
1392 d->sourceGempub = NULL;
1393 reset_GmDocument(d->doc);
1394 resetWideRuns_DocumentWidget_(d);
1395 d->state = fetching_RequestState;
1396 /* Do the fetch. */ {
1397 d->initNormScrollY = recent->normScrollY;
1398 /* Use the cached response data. */
1399 updateTrust_DocumentWidget_(d, resp);
1400 d->sourceTime = resp->when;
1401 d->sourceStatus = success_GmStatusCode;
1402 format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached"));
1403 set_Block(&d->sourceContent, &resp->body);
1404 updateDocument_DocumentWidget_(d, resp, iTrue);
1405 postProcessRequestContent_DocumentWidget_(d, iTrue);
1406 }
1407 d->state = ready_RequestState;
1408 init_Anim(&d->altTextOpacity, 0);
1409 reset_SmoothScroll(&d->scrollY);
1410 init_Anim(&d->scrollY.pos, d->initNormScrollY * size_GmDocument(d->doc).y);
1411 updateSideOpacity_DocumentWidget_(d, iFalse);
1412 updateVisible_DocumentWidget_(d);
1413 moveSpan_SmoothScroll(&d->scrollY, 0, 0); /* clamp position to new max */
1414 cacheDocumentGlyphs_DocumentWidget_(d);
1415 d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag;
1416 postCommandf_Root(as_Widget(d)->root, "document.changed doc:%p url:%s", d, cstr_String(d->mod.url));
1417 return iTrue; 1424 return iTrue;
1418 } 1425 }
1419 else if (!isEmpty_String(d->mod.url)) { 1426 else if (!isEmpty_String(d->mod.url)) {
@@ -4413,6 +4420,20 @@ void setUrlFromCache_DocumentWidget(iDocumentWidget *d, const iString *url, iBoo
4413 } 4420 }
4414} 4421}
4415 4422
4423void setUrlAndSource_DocumentWidget(iDocumentWidget *d, const iString *url, const iString *mime,
4424 const iBlock *source) {
4425 setLinkNumberMode_DocumentWidget_(d, iFalse);
4426 set_String(d->mod.url, url);
4427 parseUser_DocumentWidget_(d);
4428 iGmResponse *resp = new_GmResponse();
4429 resp->statusCode = success_GmStatusCode;
4430 initCurrent_Time(&resp->when);
4431 set_String(&resp->meta, mime);
4432 set_Block(&resp->body, source);
4433 updateFromCachedResponse_DocumentWidget_(d, 0, resp);
4434 delete_GmResponse(resp);
4435}
4436
4416iDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) { 4437iDocumentWidget *duplicate_DocumentWidget(const iDocumentWidget *orig) {
4417 iDocumentWidget *d = new_DocumentWidget(); 4438 iDocumentWidget *d = new_DocumentWidget();
4418 delete_History(d->mod.history); 4439 delete_History(d->mod.history);
diff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h
index 12603437..c038f981 100644
--- a/src/ui/documentwidget.h
+++ b/src/ui/documentwidget.h
@@ -47,6 +47,7 @@ int documentWidth_DocumentWidget (const iDocumentWidget *);
47 47
48void setUrl_DocumentWidget (iDocumentWidget *, const iString *url); 48void setUrl_DocumentWidget (iDocumentWidget *, const iString *url);
49void setUrlFromCache_DocumentWidget (iDocumentWidget *, const iString *url, iBool isFromCache); 49void setUrlFromCache_DocumentWidget (iDocumentWidget *, const iString *url, iBool isFromCache);
50void setUrlAndSource_DocumentWidget (iDocumentWidget *, const iString *url, const iString *mime, const iBlock *source);
50void setInitialScroll_DocumentWidget (iDocumentWidget *, float normScrollY); /* set after content received */ 51void setInitialScroll_DocumentWidget (iDocumentWidget *, float normScrollY); /* set after content received */
51void setRedirectCount_DocumentWidget (iDocumentWidget *, int count); 52void setRedirectCount_DocumentWidget (iDocumentWidget *, int count);
52void setSource_DocumentWidget (iDocumentWidget *, const iString *sourceText); 53void setSource_DocumentWidget (iDocumentWidget *, const iString *sourceText);
diff --git a/src/ui/root.c b/src/ui/root.c
index 1698a5d4..9a089992 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -438,10 +438,7 @@ static void updateNavBarIdentity_(iWidget *navBar) {
438 setFlags_Widget(tool, selected_WidgetFlag, ident != NULL); 438 setFlags_Widget(tool, selected_WidgetFlag, ident != NULL);
439 /* Update menu. */ 439 /* Update menu. */
440 iLabelWidget *idItem = child_Widget(findChild_Widget(button, "menu"), 0); 440 iLabelWidget *idItem = child_Widget(findChild_Widget(button, "menu"), 0);
441 iString *subjectName = ident ? collect_String(subject_TlsCertificate(ident->cert)) : NULL; 441 const iString *subjectName = ident ? name_GmIdentity(ident) : NULL;
442 if (subjectName && startsWith_String(subjectName, "CN = ")) {
443 remove_Block(&subjectName->chars, 0, 5);
444 }
445 setTextCStr_LabelWidget( 442 setTextCStr_LabelWidget(
446 idItem, 443 idItem,
447 subjectName ? format_CStr(uiTextAction_ColorEscape "%s", cstr_String(subjectName)) 444 subjectName ? format_CStr(uiTextAction_ColorEscape "%s", cstr_String(subjectName))
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 556ae951..f9bdbf67 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -169,9 +169,10 @@ static void updateContextMenu_SidebarWidget_(iSidebarWidget *d) {
169 { "---", 0, 0, NULL }, 169 { "---", 0, 0, NULL },
170 { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" }, 170 { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" },
171 { "${ident.fingerprint}", 0, 0, "ident.fingerprint" }, 171 { "${ident.fingerprint}", 0, 0, "ident.fingerprint" },
172 { export_Icon " ${ident.export}", 0, 0, "ident.export" },
172 { "---", 0, 0, NULL }, 173 { "---", 0, 0, NULL },
173 { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" }, 174 { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" },
174 }, 8); 175 }, 9);
175 /* Used URLs. */ 176 /* Used URLs. */
176 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d); 177 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d);
177 if (ident) { 178 if (ident) {
@@ -440,10 +441,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
440 iSidebarItem *item = new_SidebarItem(); 441 iSidebarItem *item = new_SidebarItem();
441 item->id = (uint32_t) index_PtrArrayConstIterator(&i); 442 item->id = (uint32_t) index_PtrArrayConstIterator(&i);
442 item->icon = 0x1f464; /* person */ 443 item->icon = 0x1f464; /* person */
443 set_String(&item->label, collect_String(subject_TlsCertificate(ident->cert))); 444 set_String(&item->label, name_GmIdentity(ident));
444 if (startsWith_String(&item->label, "CN = ")) {
445 remove_Block(&item->label.chars, 0, 5);
446 }
447 iDate until; 445 iDate until;
448 validUntil_TlsCertificate(ident->cert, &until); 446 validUntil_TlsCertificate(ident->cert, &until);
449 const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl); 447 const iBool isActive = isUsedOn_GmIdentity(ident, tabUrl);
@@ -480,11 +478,11 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
480 addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0); 478 addActionButton_SidebarWidget_(d, add_Icon " ${sidebar.action.ident.new}", "ident.new", 0);
481 addActionButton_SidebarWidget_(d, "${sidebar.action.ident.import}", "ident.import", 0); 479 addActionButton_SidebarWidget_(d, "${sidebar.action.ident.import}", "ident.import", 0);
482 } 480 }
481 /*
483 const iMenuItem menuItems[] = { 482 const iMenuItem menuItems[] = {
484 { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" }, 483 { person_Icon " ${ident.use}", 0, 0, "ident.use arg:1" },
485 { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" }, 484 { close_Icon " ${ident.stopuse}", 0, 0, "ident.use arg:0" },
486 { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" }, 485 { close_Icon " ${ident.stopuse.all}", 0, 0, "ident.use arg:0 clear:1" },
487 { "${ident.showuse}", 0, 0, "ident.showuse" },
488 { "---", 0, 0, NULL }, 486 { "---", 0, 0, NULL },
489 { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" }, 487 { edit_Icon " ${menu.edit.notes}", 0, 0, "ident.edit" },
490 { "${ident.fingerprint}", 0, 0, "ident.fingerprint" }, 488 { "${ident.fingerprint}", 0, 0, "ident.fingerprint" },
@@ -494,6 +492,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
494 { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" }, 492 { delete_Icon " " uiTextCaution_ColorEscape "${ident.delete}", 0, 0, "ident.delete confirm:1" },
495 }; 493 };
496 d->menu = makeMenu_Widget(as_Widget(d), menuItems, iElemCount(menuItems)); 494 d->menu = makeMenu_Widget(as_Widget(d), menuItems, iElemCount(menuItems));
495 */
497 break; 496 break;
498 } 497 }
499 default: 498 default:
@@ -792,6 +791,9 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, si
792 } 791 }
793 case identities_SidebarMode: { 792 case identities_SidebarMode: {
794 d->contextItem = item; 793 d->contextItem = item;
794 if (d->contextIndex != iInvalidPos) {
795 invalidateItem_ListWidget(d->list, d->contextIndex);
796 }
795 d->contextIndex = itemIndex; 797 d->contextIndex = itemIndex;
796 if (itemIndex < numItems_ListWidget(d->list)) { 798 if (itemIndex < numItems_ListWidget(d->list)) {
797 updateContextMenu_SidebarWidget_(d); 799 updateContextMenu_SidebarWidget_(d);
@@ -1277,6 +1279,20 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1277 } 1279 }
1278 return iTrue; 1280 return iTrue;
1279 } 1281 }
1282 else if (isCommand_Widget(w, ev, "ident.export")) {
1283 const iGmIdentity *ident = menuIdentity_SidebarWidget_(d);
1284 if (ident) {
1285 iString *pem = collect_String(pem_TlsCertificate(ident->cert));
1286 append_String(pem, collect_String(privateKeyPem_TlsCertificate(ident->cert)));
1287 iDocumentWidget *expTab = newTab_App(NULL, iTrue);
1288 setUrlAndSource_DocumentWidget(
1289 expTab,
1290 collectNewFormat_String("file:%s.pem", cstr_String(name_GmIdentity(ident))),
1291 collectNewCStr_String("text/plain"),
1292 utf8_String(pem));
1293 }
1294 return iTrue;
1295 }
1280 else if (isCommand_Widget(w, ev, "ident.setnotes")) { 1296 else if (isCommand_Widget(w, ev, "ident.setnotes")) {
1281 iGmIdentity *ident = pointerLabel_Command(cmd, "ident"); 1297 iGmIdentity *ident = pointerLabel_Command(cmd, "ident");
1282 if (ident) { 1298 if (ident) {
@@ -1385,7 +1401,7 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1385 d->contextIndex = iInvalidPos; 1401 d->contextIndex = iInvalidPos;
1386 } 1402 }
1387 } 1403 }
1388 if (d->menu && ev->type == SDL_MOUSEBUTTONDOWN) { 1404 if ((d->menu || d->mode == identities_SidebarMode )&& ev->type == SDL_MOUSEBUTTONDOWN) {
1389 if (ev->button.button == SDL_BUTTON_RIGHT) { 1405 if (ev->button.button == SDL_BUTTON_RIGHT) {
1390 d->contextItem = NULL; 1406 d->contextItem = NULL;
1391 if (!isVisible_Widget(d->menu)) { 1407 if (!isVisible_Widget(d->menu)) {
@@ -1457,11 +1473,13 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1457 (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) || 1473 (!cmdClear && cmdUse && isUsedOn_GmIdentity(ident, docUrl)) ||
1458 (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl))); 1474 (!cmdClear && !cmdUse && !isUsedOn_GmIdentity(ident, docUrl)));
1459 } 1475 }
1476 /*
1460 else if (equal_Command(cmdItem, "ident.showuse")) { 1477 else if (equal_Command(cmdItem, "ident.showuse")) {
1461 setFlags_Widget(as_Widget(menuItem), 1478 setFlags_Widget(as_Widget(menuItem),
1462 disabled_WidgetFlag, 1479 disabled_WidgetFlag,
1463 !isUsed_GmIdentity(ident)); 1480 !isUsed_GmIdentity(ident));
1464 } 1481 }
1482 */
1465 } 1483 }
1466 } 1484 }
1467 } 1485 }