summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
8 files changed, 90 insertions, 44 deletions
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 }