summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-11-21 14:35:32 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-11-21 14:35:32 +0200
commitc58985ed3105ff7fc29fc0d53ba81ba55882e05e (patch)
tree0dd4e254645ce7478a8fc6e01d7f7fa1e51784e4
parent67f1a5b152ca90fd8346bd39957905edaf3fb1cc (diff)
Site-specific Titan upload identity
The identity to be used for uploads is now in sitespec.ini, so it applies to an entire site root. This should match actual use cases better than having URL-specific identities. Also fixed an issue with native menus. Replacing the items with new ones was not implemented. IssueID #379
-rw-r--r--res/about/version.gmi2
-rw-r--r--src/gmcerts.c6
-rw-r--r--src/sitespec.c51
-rw-r--r--src/sitespec.h9
-rw-r--r--src/ui/uploadwidget.c45
-rw-r--r--src/ui/util.c50
-rw-r--r--src/ui/util.h1
7 files changed, 129 insertions, 35 deletions
diff --git a/res/about/version.gmi b/res/about/version.gmi
index 020373e4..b5750c8c 100644
--- a/res/about/version.gmi
+++ b/res/about/version.gmi
@@ -8,6 +8,8 @@
8 8
9## 1.8.3 9## 1.8.3
10* Fixed clicking on UI elements that are over the page top banner. The banner would always get clicked instead. 10* Fixed clicking on UI elements that are over the page top banner. The banner would always get clicked instead.
11* Titan upload identity is remembered as a site-specific setting. It is no longer affected by selections in the Identities sidebar.
12* macOS: Fixed updating items in native menus, e.g., upload identity selection.
11 13
12## 1.8.2 14## 1.8.2
13* Fixed encoding of `+` characters in URLs as per RFC 3986. 15* Fixed encoding of `+` characters in URLs as per RFC 3986.
diff --git a/src/gmcerts.c b/src/gmcerts.c
index 36fd7d55..f95fea7d 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -295,6 +295,9 @@ static void loadIdentities_GmCerts_(iGmCerts *d) {
295} 295}
296 296
297iGmIdentity *findIdentity_GmCerts(iGmCerts *d, const iBlock *fingerprint) { 297iGmIdentity *findIdentity_GmCerts(iGmCerts *d, const iBlock *fingerprint) {
298 if (isEmpty_Block(fingerprint)) {
299 return NULL;
300 }
298 iForEach(PtrArray, i, &d->idents) { 301 iForEach(PtrArray, i, &d->idents) {
299 iGmIdentity *ident = i.ptr; 302 iGmIdentity *ident = i.ptr;
300 if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */ 303 if (cmp_Block(fingerprint, &ident->fingerprint) == 0) { /* TODO: could use a hash */
@@ -549,6 +552,9 @@ const iGmIdentity *constIdentity_GmCerts(const iGmCerts *d, unsigned int id) {
549} 552}
550 553
551const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) { 554const iGmIdentity *identityForUrl_GmCerts(const iGmCerts *d, const iString *url) {
555 if (isEmpty_String(url)) {
556 return NULL;
557 }
552 lock_Mutex(d->mtx); 558 lock_Mutex(d->mtx);
553 const iGmIdentity *found = NULL; 559 const iGmIdentity *found = NULL;
554 iConstForEach(PtrArray, i, &d->idents) { 560 iConstForEach(PtrArray, i, &d->idents) {
diff --git a/src/sitespec.c b/src/sitespec.c
index 0332af2d..6f4546f0 100644
--- a/src/sitespec.c
+++ b/src/sitespec.c
@@ -33,17 +33,19 @@ iDeclareObjectConstruction(SiteParams)
33struct Impl_SiteParams { 33struct Impl_SiteParams {
34 iObject object; 34 iObject object;
35 uint16_t titanPort; 35 uint16_t titanPort;
36 iString titanIdentity; /* fingerprint */
36 int dismissWarnings; 37 int dismissWarnings;
37 /* TODO: theme seed, style settings */ 38 /* TODO: theme seed, style settings */
38}; 39};
39 40
40void init_SiteParams(iSiteParams *d) { 41void init_SiteParams(iSiteParams *d) {
41 d->titanPort = 0; /* undefined */ 42 d->titanPort = 0; /* undefined */
43 init_String(&d->titanIdentity);
42 d->dismissWarnings = 0; 44 d->dismissWarnings = 0;
43} 45}
44 46
45void deinit_SiteParams(iSiteParams *d) { 47void deinit_SiteParams(iSiteParams *d) {
46 iUnused(d); 48 deinit_String(&d->titanIdentity);
47} 49}
48 50
49iDefineClass(SiteParams) 51iDefineClass(SiteParams)
@@ -122,6 +124,9 @@ static void handleIniKeyValue_SiteSpec_(void *context, const iString *table, con
122 if (!cmp_String(key, "titanPort")) { 124 if (!cmp_String(key, "titanPort")) {
123 d->loadParams->titanPort = number_TomlValue(value); 125 d->loadParams->titanPort = number_TomlValue(value);
124 } 126 }
127 else if (!cmp_String(key, "titanIdentity") && value->type == string_TomlType) {
128 set_String(&d->loadParams->titanIdentity, value->value.string);
129 }
125 else if (!cmp_String(key, "dismissWarnings") && value->type == int64_TomlType) { 130 else if (!cmp_String(key, "dismissWarnings") && value->type == int64_TomlType) {
126 d->loadParams->dismissWarnings = value->value.int64; 131 d->loadParams->dismissWarnings = value->value.int64;
127 } 132 }
@@ -152,6 +157,10 @@ static void save_SiteSpec_(iSiteSpec *d) {
152 if (params->titanPort) { 157 if (params->titanPort) {
153 appendFormat_String(buf, "titanPort = %u\n", params->titanPort); 158 appendFormat_String(buf, "titanPort = %u\n", params->titanPort);
154 } 159 }
160 if (!isEmpty_String(&params->titanIdentity)) {
161 appendFormat_String(
162 buf, "titanIdentity = \"%s\"\n", cstr_String(&params->titanIdentity));
163 }
155 if (params->dismissWarnings) { 164 if (params->dismissWarnings) {
156 appendFormat_String(buf, "dismissWarnings = 0x%x\n", params->dismissWarnings); 165 appendFormat_String(buf, "dismissWarnings = 0x%x\n", params->dismissWarnings);
157 } 166 }
@@ -205,6 +214,30 @@ void setValue_SiteSpec(const iString *site, enum iSiteSpecKey key, int value) {
205 } 214 }
206} 215}
207 216
217void setValueString_SiteSpec(const iString *site, enum iSiteSpecKey key, const iString *value) {
218 iSiteSpec *d = &siteSpec_;
219 const iString *hashKey = collect_String(lower_String(site));
220 iSiteParams *params = value_StringHash(&d->sites, hashKey);
221 if (!params) {
222 params = new_SiteParams();
223 insert_StringHash(&d->sites, hashKey, params);
224 }
225 iBool needSave = iFalse;
226 switch (key) {
227 case titanIdentity_SiteSpecKey:
228 if (!equal_String(&params->titanIdentity, value)) {
229 needSave = iTrue;
230 set_String(&params->titanIdentity, value);
231 }
232 break;
233 default:
234 break;
235 }
236 if (needSave) {
237 save_SiteSpec_(d);
238 }
239}
240
208int value_SiteSpec(const iString *site, enum iSiteSpecKey key) { 241int value_SiteSpec(const iString *site, enum iSiteSpecKey key) {
209 iSiteSpec *d = &siteSpec_; 242 iSiteSpec *d = &siteSpec_;
210 const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site))); 243 const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site)));
@@ -220,3 +253,17 @@ int value_SiteSpec(const iString *site, enum iSiteSpecKey key) {
220 return 0; 253 return 0;
221 } 254 }
222} 255}
256
257const iString *valueString_SiteSpec(const iString *site, enum iSiteSpecKey key) {
258 iSiteSpec *d = &siteSpec_;
259 const iSiteParams *params = constValue_StringHash(&d->sites, collect_String(lower_String(site)));
260 if (!params) {
261 return 0;
262 }
263 switch (key) {
264 case titanIdentity_SiteSpecKey:
265 return &params->titanIdentity;
266 default:
267 return collectNew_String();
268 }
269}
diff --git a/src/sitespec.h b/src/sitespec.h
index 6b64f073..5adaeb8c 100644
--- a/src/sitespec.h
+++ b/src/sitespec.h
@@ -28,11 +28,16 @@ iDeclareType(SiteSpec)
28 28
29enum iSiteSpecKey { 29enum iSiteSpecKey {
30 titanPort_SiteSpecKey, 30 titanPort_SiteSpecKey,
31 titanIdentity_SiteSpecKey,
31 dismissWarnings_SiteSpecKey, 32 dismissWarnings_SiteSpecKey,
32}; 33};
33 34
34void init_SiteSpec (const char *saveDir); 35void init_SiteSpec (const char *saveDir);
35void deinit_SiteSpec (void); 36void deinit_SiteSpec (void);
36 37
37void setValue_SiteSpec (const iString *site, enum iSiteSpecKey key, int value); /* changes saved immediately */ 38/* changes saved immediately */
38int value_SiteSpec (const iString *site, enum iSiteSpecKey key); 39void setValue_SiteSpec (const iString *site, enum iSiteSpecKey key, int value);
40void setValueString_SiteSpec (const iString *site, enum iSiteSpecKey key, const iString *value);
41
42int value_SiteSpec (const iString *site, enum iSiteSpecKey key);
43const iString * valueString_SiteSpec (const iString *site, enum iSiteSpecKey key);
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index 90df1958..bad00071 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -45,7 +45,7 @@ iDefineObjectConstruction(UploadWidget)
45 45
46enum iUploadIdentity { 46enum iUploadIdentity {
47 none_UploadIdentity, 47 none_UploadIdentity,
48 defaultForUrl_UploadIdentity, 48 defaultForSite_UploadIdentity,
49 dropdown_UploadIdentity, 49 dropdown_UploadIdentity,
50}; 50};
51 51
@@ -104,9 +104,16 @@ static void updateInputMaxHeight_UploadWidget_(iUploadWidget *d) {
104 (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input)))); 104 (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input))));
105} 105}
106 106
107static const iGmIdentity *titanIdentityForUrl_(const iString *url) {
108 return findIdentity_GmCerts(
109 certs_App(),
110 collect_Block(hexDecode_Rangecc(range_String(valueString_SiteSpec(
111 collectNewRange_String(urlRoot_String(url)), titanIdentity_SiteSpecKey)))));
112}
113
107static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) { 114static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) {
108 iArray *items = collectNew_Array(sizeof(iMenuItem)); 115 iArray *items = collectNew_Array(sizeof(iMenuItem));
109 const iGmIdentity *urlId = identityForUrl_GmCerts(certs_App(), &d->url); 116 const iGmIdentity *urlId = titanIdentityForUrl_(&d->url);
110 pushBack_Array(items, 117 pushBack_Array(items,
111 &(iMenuItem){ format_CStr("${dlg.upload.id.default} (%s)", 118 &(iMenuItem){ format_CStr("${dlg.upload.id.default} (%s)",
112 urlId ? cstr_String(name_GmIdentity(urlId)) 119 urlId ? cstr_String(name_GmIdentity(urlId))
@@ -147,7 +154,7 @@ void init_UploadWidget(iUploadWidget *d) {
147 d->request = NULL; 154 d->request = NULL;
148 init_String(&d->filePath); 155 init_String(&d->filePath);
149 d->fileSize = 0; 156 d->fileSize = 0;
150 d->idMode = defaultForUrl_UploadIdentity; 157 d->idMode = defaultForSite_UploadIdentity;
151 init_Block(&d->idFingerprint, 0); 158 init_Block(&d->idFingerprint, 0);
152 const iMenuItem actions[] = { 159 const iMenuItem actions[] = {
153 { "${upload.port}", 0, 0, "upload.setport" }, 160 { "${upload.port}", 0, 0, "upload.setport" },
@@ -289,16 +296,22 @@ void deinit_UploadWidget(iUploadWidget *d) {
289 296
290static void remakeIdentityItems_UploadWidget_(iUploadWidget *d) { 297static void remakeIdentityItems_UploadWidget_(iUploadWidget *d) {
291 iWidget *dropMenu = findChild_Widget(findChild_Widget(as_Widget(d), "upload.id"), "menu"); 298 iWidget *dropMenu = findChild_Widget(findChild_Widget(as_Widget(d), "upload.id"), "menu");
292 releaseChildren_Widget(dropMenu);
293 const iArray *items = makeIdentityItems_UploadWidget_(d); 299 const iArray *items = makeIdentityItems_UploadWidget_(d);
294 makeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items)); 300 /* TODO: Make the following a utility method. */
301 if (flags_Widget(dropMenu) & nativeMenu_WidgetFlag) {
302 setNativeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items));
303 }
304 else {
305 releaseChildren_Widget(dropMenu);
306 makeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items));
307 }
295} 308}
296 309
297static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) { 310static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) {
298 updateDropdownSelection_LabelWidget( 311 updateDropdownSelection_LabelWidget(
299 findChild_Widget(as_Widget(d), "upload.id"), 312 findChild_Widget(as_Widget(d), "upload.id"),
300 d->idMode == none_UploadIdentity ? " arg:0" 313 d->idMode == none_UploadIdentity ? " arg:0"
301 : d->idMode == defaultForUrl_UploadIdentity 314 : d->idMode == defaultForSite_UploadIdentity
302 ? " arg:1" 315 ? " arg:1"
303 : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint)))); 316 : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint))));
304} 317}
@@ -422,7 +435,7 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
422 } 435 }
423 else if (arg_Command(cmd)) { 436 else if (arg_Command(cmd)) {
424 clear_Block(&d->idFingerprint); 437 clear_Block(&d->idFingerprint);
425 d->idMode = defaultForUrl_UploadIdentity; 438 d->idMode = defaultForSite_UploadIdentity;
426 } 439 }
427 else { 440 else {
428 clear_Block(&d->idFingerprint); 441 clear_Block(&d->idFingerprint);
@@ -452,19 +465,27 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
452 setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_); 465 setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_);
453 setUserData_Object(d->request, d); 466 setUserData_Object(d->request, d);
454 setUrl_GmRequest(d->request, &d->url); 467 setUrl_GmRequest(d->request, &d->url);
468 const iString *site = collectNewRange_String(urlRoot_String(&d->url));
455 switch (d->idMode) { 469 switch (d->idMode) {
456 case defaultForUrl_UploadIdentity:
457 break; /* GmRequest handles it */
458 case none_UploadIdentity: 470 case none_UploadIdentity:
459 setIdentity_GmRequest(d->request, NULL); 471 /* Ensure no identity will be used for this specific URL. */
460 signOut_GmCerts(certs_App(), url_GmRequest(d->request)); 472 signOut_GmCerts(certs_App(), url_GmRequest(d->request));
473 setValueString_SiteSpec(site, titanIdentity_SiteSpecKey, collectNew_String());
461 break; 474 break;
462 case dropdown_UploadIdentity: { 475 case dropdown_UploadIdentity: {
463 iGmIdentity *ident = findIdentity_GmCerts(certs_App(), &d->idFingerprint); 476 iGmIdentity *ident = findIdentity_GmCerts(certs_App(), &d->idFingerprint);
464 setIdentity_GmRequest(d->request, ident); 477 if (ident) {
465 signIn_GmCerts(certs_App(), ident, url_GmRequest(d->request)); 478 setValueString_SiteSpec(site,
479 titanIdentity_SiteSpecKey,
480 collect_String(hexEncode_Block(&ident->fingerprint)));
481 }
466 break; 482 break;
467 } 483 }
484 default:
485 break;
486 }
487 if (d->idMode != none_UploadIdentity) {
488 setIdentity_GmRequest(d->request, titanIdentityForUrl_(&d->url));
468 } 489 }
469 if (isText) { 490 if (isText) {
470 /* Uploading text. */ 491 /* Uploading text. */
diff --git a/src/ui/util.c b/src/ui/util.c
index 2624bf2b..0a9dde0c 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -809,14 +809,27 @@ static void deleteMenuItems_(iArray *items) {
809 delete_Array(items); 809 delete_Array(items);
810} 810}
811 811
812iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { 812void releaseNativeMenu_Widget(iWidget *d) {
813 iWidget *menu = new_Widget();
814#if defined (iHaveNativeContextMenus) 813#if defined (iHaveNativeContextMenus)
815 setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue); 814 iArray *items = userData_Object(d);
815 if (items) {
816 iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);
817 iAssert(items);
818 deleteMenuItems_(items);
819 setUserData_Object(d, NULL);
820 }
821#else
822 iUnused(d);
823#endif
824}
825
826void setNativeMenuItems_Widget(iWidget *menu, const iMenuItem *items, size_t n) {
827#if defined (iHaveNativeContextMenus)
828 iAssert(flags_Widget(menu) & nativeMenu_WidgetFlag);
829 releaseNativeMenu_Widget(menu);
816 setUserData_Object(menu, deepCopyMenuItems_(menu, items, n)); 830 setUserData_Object(menu, deepCopyMenuItems_(menu, items, n));
817 addChild_Widget(parent, menu);
818 iRelease(menu); /* owned by parent now */
819 /* Keyboard shortcuts still need to triggerable via the menu, although the items don't exist. */ { 831 /* Keyboard shortcuts still need to triggerable via the menu, although the items don't exist. */ {
832 releaseChildren_Widget(menu);
820 for (size_t i = 0; i < n; i++) { 833 for (size_t i = 0; i < n; i++) {
821 const iMenuItem *item = &items[i]; 834 const iMenuItem *item = &items[i];
822 if (item->key) { 835 if (item->key) {
@@ -824,6 +837,17 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
824 } 837 }
825 } 838 }
826 } 839 }
840#endif
841}
842
843iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {
844 iWidget *menu = new_Widget();
845#if defined (iHaveNativeContextMenus)
846 setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue);
847 addChild_Widget(parent, menu);
848 iRelease(menu); /* owned by parent now */
849 setUserData_Object(menu, NULL);
850 setNativeMenuItems_Widget(menu, items, n);
827#else 851#else
828 /* Non-native custom popup menu. This may still be displayed inside a separate window. */ 852 /* Non-native custom popup menu. This may still be displayed inside a separate window. */
829 setDrawBufferEnabled_Widget(menu, iTrue); 853 setDrawBufferEnabled_Widget(menu, iTrue);
@@ -990,18 +1014,6 @@ iLocalDef iBool isUsingMenuPopupWindows_(void) {
990#endif 1014#endif
991} 1015}
992 1016
993void releaseNativeMenu_Widget(iWidget *d) {
994#if defined (iHaveNativeContextMenus)
995 iArray *items = userData_Object(d);
996 iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);
997 iAssert(items);
998 deleteMenuItems_(items);
999 setUserData_Object(d, NULL);
1000#else
1001 iUnused(d);
1002#endif
1003}
1004
1005void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { 1017void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) {
1006 const iBool postCommands = (menuOpenFlags & postCommands_MenuOpenFlags) != 0; 1018 const iBool postCommands = (menuOpenFlags & postCommands_MenuOpenFlags) != 0;
1007#if defined (iHaveNativeContextMenus) 1019#if defined (iHaveNativeContextMenus)
@@ -1263,8 +1275,8 @@ void updateDropdownSelection_LabelWidget(iLabelWidget *dropButton, const char *s
1263 iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand); 1275 iMenuItem *item = findNativeMenuItem_Widget(menu, selectedCommand);
1264 if (item) { 1276 if (item) {
1265 setSelected_NativeMenuItem(item, iTrue); 1277 setSelected_NativeMenuItem(item, iTrue);
1266 updateText_LabelWidget(dropButton, 1278 updateText_LabelWidget(
1267 removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label))); 1279 dropButton, removeMenuItemLabelPrefixes_String(collectNewCStr_String(item->label)));
1268 } 1280 }
1269 return; 1281 return;
1270 } 1282 }
diff --git a/src/ui/util.h b/src/ui/util.h
index cf96dfe4..52b3a692 100644
--- a/src/ui/util.h
+++ b/src/ui/util.h
@@ -249,6 +249,7 @@ void setMenuItemDisabled_Widget (iWidget *menu, const char *comm
249void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable); 249void setMenuItemDisabledByIndex_Widget(iWidget *menu, size_t index, iBool disable);
250void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel); 250void setMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel);
251void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel); 251void setMenuItemLabelByIndex_Widget (iWidget *menu, size_t index, const char *newLabel);
252void setNativeMenuItems_Widget (iWidget *, const iMenuItem *items, size_t n);
252 253
253int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ 254int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */
254 255