Fossil SCM

Use the "name" query parameter to select a report number. The legacy "rn" query parameter still works, but generated hyperlinks now use the new format.

drh 2022-11-18 19:20 json-meta-data
Commit 3048c04b2a430afb594810c768a16cbef67b5c3b286b9a11e3b9230c43726561
1 file changed +58 -19
+58 -19
--- src/report.c
+++ src/report.c
@@ -75,29 +75,29 @@
7575
cnt++;
7676
blob_appendf(&ril, "<li>");
7777
if( zTitle[0] == '_' ){
7878
blob_appendf(&ril, "%s", zTitle);
7979
} else {
80
- blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
80
+ blob_appendf(&ril, "%z%h</a>", href("%R/rptview/%d", rn), zTitle);
8181
}
8282
blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
8383
if( g.perm.Write && zOwner && zOwner[0] ){
8484
blob_appendf(&ril, "(by <i>%h</i>) ", zOwner);
8585
}
8686
if( g.perm.TktFmt ){
8787
blob_appendf(&ril, "[%zcopy</a>] ",
88
- href("%R/rptedit?rn=%d&copy=1", rn));
88
+ href("%R/rptedit/%d?copy=1", rn));
8989
}
9090
if( g.perm.Admin
9191
|| (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
9292
){
9393
blob_appendf(&ril, "[%zedit</a>]",
94
- href("%R/rptedit?rn=%d", rn));
94
+ href("%R/rptedit/%d", rn));
9595
}
9696
if( g.perm.TktFmt ){
9797
blob_appendf(&ril, "[%zsql</a>]",
98
- href("%R/rptsql?rn=%d", rn));
98
+ href("%R/rptsql/%d", rn));
9999
}
100100
if( fossil_strcmp(zTitle, defaultReport)==0 ){
101101
blob_appendf(&ril, "&nbsp;← default");
102102
}
103103
blob_appendf(&ril, "</li>\n");
@@ -335,17 +335,53 @@
335335
sqlite3_finalize(pStmt);
336336
}
337337
report_unrestrict_sql();
338338
return zErr;
339339
}
340
+
341
+/*
342
+** Get a report number from query parameters. This can be done in various
343
+** ways:
344
+**
345
+** (1) (legacy) rn=NNN where NNN is the reportfmt.rn integer primary key.
346
+**
347
+** (2) name=NNN where NNN is the rn.
348
+**
349
+** (3) name=TAG where TAG matches reportfmt.jx->>tag
350
+**
351
+** Regardless of how the report is specified, return the primary key, rn.
352
+** Return 0 if not found.
353
+*/
354
+static int report_number(void){
355
+ int rn;
356
+ const char *zName;
357
+ char *zEnd;
358
+
359
+ /* Case (1) */
360
+ rn = atoi(PD("rn","0"));
361
+ if( rn>0 ) return rn;
362
+
363
+ zName = P("name");
364
+ if( zName==0 || zName[0]==0 ) return 0;
365
+ if( fossil_isdigit(zName[0])
366
+ && (rn = strtol(zName, &zEnd, 10))>0
367
+ && zEnd[0]==0
368
+ ){
369
+ /* Case 2 */
370
+ return rn;
371
+ }
372
+
373
+ rn = db_int(0, "SELECT rn FROM reportfmt WHERE jx->>'tag'==%Q", zName);
374
+ return rn;
375
+}
340376
341377
/*
342378
** WEBPAGE: rptsql
343
-** URL: /rptsql?rn=N
379
+** URL: /rptsql/N
344380
**
345
-** Display the SQL query used to generate a ticket report. The rn=N
346
-** query parameter identifies the specific report number to be displayed.
381
+** Display the SQL query used to generate a ticket report. The N value
382
+** is either the report number of a report tag.
347383
*/
348384
void view_see_sql(void){
349385
int rn;
350386
const char *zTitle;
351387
const char *zSQL;
@@ -356,11 +392,11 @@
356392
login_check_credentials();
357393
if( !g.perm.TktFmt ){
358394
login_needed(g.anon.TktFmt);
359395
return;
360396
}
361
- rn = atoi(PD("rn","0"));
397
+ rn = report_number();
362398
db_prepare(&q, "SELECT title, sqlcode, owner, cols "
363399
"FROM reportfmt WHERE rn=%d",rn);
364400
style_set_current_feature("report");
365401
style_header("SQL For Report Format Number %d", rn);
366402
if( db_step(&q)!=SQLITE_ROW ){
@@ -396,11 +432,13 @@
396432
** WEBPAGE: rptedit
397433
**
398434
** Create (/rptnew) or edit (/rptedit) a ticket report format.
399435
** Query parameters:
400436
**
401
-** rn=N Ticket report number. (required)
437
+** name=N Ticket report number or tag.
438
+** rn=N Ticket report number (legacy).
439
+** ^^^-- one of the two previous is required.
402440
** t=TITLE Title of the report format
403441
** w=USER Owner of the report format
404442
** s=SQL SQL text used to implement the report
405443
** k=KEY Color key
406444
** d=DESC Optional descriptive text
@@ -425,11 +463,11 @@
425463
login_needed(g.anon.TktFmt);
426464
return;
427465
}
428466
style_set_current_feature("report");
429467
/*view_add_functions(0);*/
430
- rn = atoi(PD("rn","0"));
468
+ rn = report_number();
431469
zTitle = P("t");
432470
zOwner = PD("w",g.zLogin);
433471
z = P("s");
434472
zSQL = z ? trim_string(z) : 0;
435473
zClrKey = trim_string(PD("k",""));
@@ -506,11 +544,11 @@
506544
char *defaultReport = db_get("ticket-default-report", 0);
507545
if( fossil_strcmp(zTitle, defaultReport)==0 ){
508546
db_set("ticket-default-report", "", 0);
509547
}
510548
}
511
- cgi_redirect(mprintf("rptview?rn=%d", rn));
549
+ cgi_redirect(mprintf("rptview/%d", rn));
512550
return;
513551
}
514552
}else if( rn==0 ){
515553
zTitle = "";
516554
zSQL = ticket_report_template();
@@ -550,11 +588,11 @@
550588
}
551589
}
552590
if( zOwner==0 ) zOwner = g.zLogin;
553591
style_submenu_element("Cancel", "reportlist");
554592
if( rn>0 ){
555
- style_submenu_element("Delete", "rptedit?rn=%d&del1=1", rn);
593
+ style_submenu_element("Delete", "rptedit/%d?del1=1", rn);
556594
}
557595
style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format");
558596
if( zErr ){
559597
@ <blockquote class="reportError">%h(zErr)</blockquote>
560598
}
@@ -814,13 +852,13 @@
814852
pState->zWikiEnd = "";
815853
if( P("plaintext") ){
816854
pState->wikiFlags |= WIKI_LINKSONLY;
817855
pState->zWikiStart = "<pre class='verbatim'>";
818856
pState->zWikiEnd = "</pre>";
819
- style_submenu_element("Formatted", "%R/rptview?rn=%d", pState->rn);
857
+ style_submenu_element("Formatted", "%R/rptview/%d", pState->rn);
820858
}else{
821
- style_submenu_element("Plaintext", "%R/rptview?rn=%d&plaintext",
859
+ style_submenu_element("Plaintext", "%R/rptview/%d?plaintext",
822860
pState->rn);
823861
}
824862
}else{
825863
pState->nCol++;
826864
}
@@ -1092,18 +1130,19 @@
10921130
char *zMimetype;
10931131
int tabs;
10941132
Stmt q;
10951133
char *zErr1 = 0;
10961134
char *zErr2 = 0;
1097
-
1135
+
10981136
login_check_credentials();
10991137
if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
1138
+
1139
+ rn = report_number();
11001140
tabs = P("tablist")!=0;
11011141
db_prepare(&q,
11021142
"SELECT title, sqlcode, owner, cols, rn, jx->>'desc', jx->>'descmt'"
1103
- " FROM reportfmt WHERE rn=%d",
1104
- atoi(PD("rn","0")));
1143
+ " FROM reportfmt WHERE rn=%d", rn);
11051144
rc = db_step(&q);
11061145
if( rc!=SQLITE_ROW ){
11071146
const char *titleSearch =
11081147
defaultTitleSearch==0 || trim_string(defaultTitleSearch)[0]==0 ?
11091148
P("title") : defaultTitleSearch;
@@ -1161,14 +1200,14 @@
11611200
style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
11621201
style_submenu_element("Reports","%R/reportlist");
11631202
}
11641203
if( g.perm.Admin
11651204
|| (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1166
- style_submenu_element("Edit", "rptedit?rn=%d", rn);
1205
+ style_submenu_element("Edit", "rptedit/%d", rn);
11671206
}
11681207
if( g.perm.TktFmt ){
1169
- style_submenu_element("SQL", "rptsql?rn=%d",rn);
1208
+ style_submenu_element("SQL", "rptsql/%d",rn);
11701209
}
11711210
if( g.perm.NewTkt ){
11721211
style_submenu_element("New Ticket", "%R/tktnew");
11731212
}
11741213
style_header("%s", zTitle);
11751214
--- src/report.c
+++ src/report.c
@@ -75,29 +75,29 @@
75 cnt++;
76 blob_appendf(&ril, "<li>");
77 if( zTitle[0] == '_' ){
78 blob_appendf(&ril, "%s", zTitle);
79 } else {
80 blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
81 }
82 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
83 if( g.perm.Write && zOwner && zOwner[0] ){
84 blob_appendf(&ril, "(by <i>%h</i>) ", zOwner);
85 }
86 if( g.perm.TktFmt ){
87 blob_appendf(&ril, "[%zcopy</a>] ",
88 href("%R/rptedit?rn=%d&copy=1", rn));
89 }
90 if( g.perm.Admin
91 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
92 ){
93 blob_appendf(&ril, "[%zedit</a>]",
94 href("%R/rptedit?rn=%d", rn));
95 }
96 if( g.perm.TktFmt ){
97 blob_appendf(&ril, "[%zsql</a>]",
98 href("%R/rptsql?rn=%d", rn));
99 }
100 if( fossil_strcmp(zTitle, defaultReport)==0 ){
101 blob_appendf(&ril, "&nbsp;← default");
102 }
103 blob_appendf(&ril, "</li>\n");
@@ -335,17 +335,53 @@
335 sqlite3_finalize(pStmt);
336 }
337 report_unrestrict_sql();
338 return zErr;
339 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
341 /*
342 ** WEBPAGE: rptsql
343 ** URL: /rptsql?rn=N
344 **
345 ** Display the SQL query used to generate a ticket report. The rn=N
346 ** query parameter identifies the specific report number to be displayed.
347 */
348 void view_see_sql(void){
349 int rn;
350 const char *zTitle;
351 const char *zSQL;
@@ -356,11 +392,11 @@
356 login_check_credentials();
357 if( !g.perm.TktFmt ){
358 login_needed(g.anon.TktFmt);
359 return;
360 }
361 rn = atoi(PD("rn","0"));
362 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
363 "FROM reportfmt WHERE rn=%d",rn);
364 style_set_current_feature("report");
365 style_header("SQL For Report Format Number %d", rn);
366 if( db_step(&q)!=SQLITE_ROW ){
@@ -396,11 +432,13 @@
396 ** WEBPAGE: rptedit
397 **
398 ** Create (/rptnew) or edit (/rptedit) a ticket report format.
399 ** Query parameters:
400 **
401 ** rn=N Ticket report number. (required)
 
 
402 ** t=TITLE Title of the report format
403 ** w=USER Owner of the report format
404 ** s=SQL SQL text used to implement the report
405 ** k=KEY Color key
406 ** d=DESC Optional descriptive text
@@ -425,11 +463,11 @@
425 login_needed(g.anon.TktFmt);
426 return;
427 }
428 style_set_current_feature("report");
429 /*view_add_functions(0);*/
430 rn = atoi(PD("rn","0"));
431 zTitle = P("t");
432 zOwner = PD("w",g.zLogin);
433 z = P("s");
434 zSQL = z ? trim_string(z) : 0;
435 zClrKey = trim_string(PD("k",""));
@@ -506,11 +544,11 @@
506 char *defaultReport = db_get("ticket-default-report", 0);
507 if( fossil_strcmp(zTitle, defaultReport)==0 ){
508 db_set("ticket-default-report", "", 0);
509 }
510 }
511 cgi_redirect(mprintf("rptview?rn=%d", rn));
512 return;
513 }
514 }else if( rn==0 ){
515 zTitle = "";
516 zSQL = ticket_report_template();
@@ -550,11 +588,11 @@
550 }
551 }
552 if( zOwner==0 ) zOwner = g.zLogin;
553 style_submenu_element("Cancel", "reportlist");
554 if( rn>0 ){
555 style_submenu_element("Delete", "rptedit?rn=%d&del1=1", rn);
556 }
557 style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format");
558 if( zErr ){
559 @ <blockquote class="reportError">%h(zErr)</blockquote>
560 }
@@ -814,13 +852,13 @@
814 pState->zWikiEnd = "";
815 if( P("plaintext") ){
816 pState->wikiFlags |= WIKI_LINKSONLY;
817 pState->zWikiStart = "<pre class='verbatim'>";
818 pState->zWikiEnd = "</pre>";
819 style_submenu_element("Formatted", "%R/rptview?rn=%d", pState->rn);
820 }else{
821 style_submenu_element("Plaintext", "%R/rptview?rn=%d&plaintext",
822 pState->rn);
823 }
824 }else{
825 pState->nCol++;
826 }
@@ -1092,18 +1130,19 @@
1092 char *zMimetype;
1093 int tabs;
1094 Stmt q;
1095 char *zErr1 = 0;
1096 char *zErr2 = 0;
1097
1098 login_check_credentials();
1099 if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
 
 
1100 tabs = P("tablist")!=0;
1101 db_prepare(&q,
1102 "SELECT title, sqlcode, owner, cols, rn, jx->>'desc', jx->>'descmt'"
1103 " FROM reportfmt WHERE rn=%d",
1104 atoi(PD("rn","0")));
1105 rc = db_step(&q);
1106 if( rc!=SQLITE_ROW ){
1107 const char *titleSearch =
1108 defaultTitleSearch==0 || trim_string(defaultTitleSearch)[0]==0 ?
1109 P("title") : defaultTitleSearch;
@@ -1161,14 +1200,14 @@
1161 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1162 style_submenu_element("Reports","%R/reportlist");
1163 }
1164 if( g.perm.Admin
1165 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1166 style_submenu_element("Edit", "rptedit?rn=%d", rn);
1167 }
1168 if( g.perm.TktFmt ){
1169 style_submenu_element("SQL", "rptsql?rn=%d",rn);
1170 }
1171 if( g.perm.NewTkt ){
1172 style_submenu_element("New Ticket", "%R/tktnew");
1173 }
1174 style_header("%s", zTitle);
1175
--- src/report.c
+++ src/report.c
@@ -75,29 +75,29 @@
75 cnt++;
76 blob_appendf(&ril, "<li>");
77 if( zTitle[0] == '_' ){
78 blob_appendf(&ril, "%s", zTitle);
79 } else {
80 blob_appendf(&ril, "%z%h</a>", href("%R/rptview/%d", rn), zTitle);
81 }
82 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
83 if( g.perm.Write && zOwner && zOwner[0] ){
84 blob_appendf(&ril, "(by <i>%h</i>) ", zOwner);
85 }
86 if( g.perm.TktFmt ){
87 blob_appendf(&ril, "[%zcopy</a>] ",
88 href("%R/rptedit/%d?copy=1", rn));
89 }
90 if( g.perm.Admin
91 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
92 ){
93 blob_appendf(&ril, "[%zedit</a>]",
94 href("%R/rptedit/%d", rn));
95 }
96 if( g.perm.TktFmt ){
97 blob_appendf(&ril, "[%zsql</a>]",
98 href("%R/rptsql/%d", rn));
99 }
100 if( fossil_strcmp(zTitle, defaultReport)==0 ){
101 blob_appendf(&ril, "&nbsp;← default");
102 }
103 blob_appendf(&ril, "</li>\n");
@@ -335,17 +335,53 @@
335 sqlite3_finalize(pStmt);
336 }
337 report_unrestrict_sql();
338 return zErr;
339 }
340
341 /*
342 ** Get a report number from query parameters. This can be done in various
343 ** ways:
344 **
345 ** (1) (legacy) rn=NNN where NNN is the reportfmt.rn integer primary key.
346 **
347 ** (2) name=NNN where NNN is the rn.
348 **
349 ** (3) name=TAG where TAG matches reportfmt.jx->>tag
350 **
351 ** Regardless of how the report is specified, return the primary key, rn.
352 ** Return 0 if not found.
353 */
354 static int report_number(void){
355 int rn;
356 const char *zName;
357 char *zEnd;
358
359 /* Case (1) */
360 rn = atoi(PD("rn","0"));
361 if( rn>0 ) return rn;
362
363 zName = P("name");
364 if( zName==0 || zName[0]==0 ) return 0;
365 if( fossil_isdigit(zName[0])
366 && (rn = strtol(zName, &zEnd, 10))>0
367 && zEnd[0]==0
368 ){
369 /* Case 2 */
370 return rn;
371 }
372
373 rn = db_int(0, "SELECT rn FROM reportfmt WHERE jx->>'tag'==%Q", zName);
374 return rn;
375 }
376
377 /*
378 ** WEBPAGE: rptsql
379 ** URL: /rptsql/N
380 **
381 ** Display the SQL query used to generate a ticket report. The N value
382 ** is either the report number of a report tag.
383 */
384 void view_see_sql(void){
385 int rn;
386 const char *zTitle;
387 const char *zSQL;
@@ -356,11 +392,11 @@
392 login_check_credentials();
393 if( !g.perm.TktFmt ){
394 login_needed(g.anon.TktFmt);
395 return;
396 }
397 rn = report_number();
398 db_prepare(&q, "SELECT title, sqlcode, owner, cols "
399 "FROM reportfmt WHERE rn=%d",rn);
400 style_set_current_feature("report");
401 style_header("SQL For Report Format Number %d", rn);
402 if( db_step(&q)!=SQLITE_ROW ){
@@ -396,11 +432,13 @@
432 ** WEBPAGE: rptedit
433 **
434 ** Create (/rptnew) or edit (/rptedit) a ticket report format.
435 ** Query parameters:
436 **
437 ** name=N Ticket report number or tag.
438 ** rn=N Ticket report number (legacy).
439 ** ^^^-- one of the two previous is required.
440 ** t=TITLE Title of the report format
441 ** w=USER Owner of the report format
442 ** s=SQL SQL text used to implement the report
443 ** k=KEY Color key
444 ** d=DESC Optional descriptive text
@@ -425,11 +463,11 @@
463 login_needed(g.anon.TktFmt);
464 return;
465 }
466 style_set_current_feature("report");
467 /*view_add_functions(0);*/
468 rn = report_number();
469 zTitle = P("t");
470 zOwner = PD("w",g.zLogin);
471 z = P("s");
472 zSQL = z ? trim_string(z) : 0;
473 zClrKey = trim_string(PD("k",""));
@@ -506,11 +544,11 @@
544 char *defaultReport = db_get("ticket-default-report", 0);
545 if( fossil_strcmp(zTitle, defaultReport)==0 ){
546 db_set("ticket-default-report", "", 0);
547 }
548 }
549 cgi_redirect(mprintf("rptview/%d", rn));
550 return;
551 }
552 }else if( rn==0 ){
553 zTitle = "";
554 zSQL = ticket_report_template();
@@ -550,11 +588,11 @@
588 }
589 }
590 if( zOwner==0 ) zOwner = g.zLogin;
591 style_submenu_element("Cancel", "reportlist");
592 if( rn>0 ){
593 style_submenu_element("Delete", "rptedit/%d?del1=1", rn);
594 }
595 style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format");
596 if( zErr ){
597 @ <blockquote class="reportError">%h(zErr)</blockquote>
598 }
@@ -814,13 +852,13 @@
852 pState->zWikiEnd = "";
853 if( P("plaintext") ){
854 pState->wikiFlags |= WIKI_LINKSONLY;
855 pState->zWikiStart = "<pre class='verbatim'>";
856 pState->zWikiEnd = "</pre>";
857 style_submenu_element("Formatted", "%R/rptview/%d", pState->rn);
858 }else{
859 style_submenu_element("Plaintext", "%R/rptview/%d?plaintext",
860 pState->rn);
861 }
862 }else{
863 pState->nCol++;
864 }
@@ -1092,18 +1130,19 @@
1130 char *zMimetype;
1131 int tabs;
1132 Stmt q;
1133 char *zErr1 = 0;
1134 char *zErr2 = 0;
1135
1136 login_check_credentials();
1137 if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
1138
1139 rn = report_number();
1140 tabs = P("tablist")!=0;
1141 db_prepare(&q,
1142 "SELECT title, sqlcode, owner, cols, rn, jx->>'desc', jx->>'descmt'"
1143 " FROM reportfmt WHERE rn=%d", rn);
 
1144 rc = db_step(&q);
1145 if( rc!=SQLITE_ROW ){
1146 const char *titleSearch =
1147 defaultTitleSearch==0 || trim_string(defaultTitleSearch)[0]==0 ?
1148 P("title") : defaultTitleSearch;
@@ -1161,14 +1200,14 @@
1200 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1201 style_submenu_element("Reports","%R/reportlist");
1202 }
1203 if( g.perm.Admin
1204 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1205 style_submenu_element("Edit", "rptedit/%d", rn);
1206 }
1207 if( g.perm.TktFmt ){
1208 style_submenu_element("SQL", "rptsql/%d",rn);
1209 }
1210 if( g.perm.NewTkt ){
1211 style_submenu_element("New Ticket", "%R/tktnew");
1212 }
1213 style_header("%s", zTitle);
1214

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button