Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | All markup of the form <verbatim-ID>...</verbatim> with an options "links" or "links=BOOLEAN" attribute. Improved TH1 tracing and error reporting capabilities. Improved documentation on how reports work. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | ticket-enhancements |
| Files: | files | file ages | folders |
| SHA1: |
23c75abde4e26afd24715f69f69af057 |
| User & Date: | drh 2012-11-23 15:57:08.226 |
Context
|
2012-11-23
| ||
| 16:37 | Add the [string trim ...] command to TH1. Accept query parameters in tktview. ... (check-in: 7ba3f65382 user: drh tags: ticket-enhancements) | |
| 15:57 | All markup of the form <verbatim-ID>...</verbatim> with an options "links" or "links=BOOLEAN" attribute. Improved TH1 tracing and error reporting capabilities. Improved documentation on how reports work. ... (check-in: 23c75abde4 user: drh tags: ticket-enhancements) | |
| 01:50 | When db_open_config() is called with the useAttach parameter set to non-zero, it may need to close and reopen the database using ATTACH if that was not done previously. ... (check-in: fe453a4893 user: drh tags: trunk) | |
Changes
Changes to src/main.c.
| ︙ | ︙ | |||
1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 |
/*
** Note that the following command is used by ssh:// processing.
**
** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
*/
void cmd_test_http(void){
login_set_capabilities("sx", 0);
g.useLocalauth = 1;
cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
g.httpIn = stdin;
g.httpOut = stdout;
find_server_repository(0);
g.cgiOutput = 1;
| > > > > | 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 |
/*
** Note that the following command is used by ssh:// processing.
**
** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
*/
void cmd_test_http(void){
g.thTrace = find_option("th-trace", 0, 0)!=0;
if( g.thTrace ){
blob_zero(&g.thLog);
}
login_set_capabilities("sx", 0);
g.useLocalauth = 1;
cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
g.httpIn = stdin;
g.httpOut = stdout;
find_server_repository(0);
g.cgiOutput = 1;
|
| ︙ | ︙ |
Changes to src/report.c.
| ︙ | ︙ | |||
486 487 488 489 490 491 492 493 494 |
@
@ <li><p>If a column of the result set is named "#" then that column
@ is assumed to hold a ticket number. A hyperlink will be created from
@ that column to a detailed view of the ticket.</p></li>
@
@ <li><p>If a column of the result set is named "bgcolor" then the content
@ of that column determines the background color of the row.</p></li>
@
@ <li><p>The first column whose name begins with underscore ("_") and all
| > > > > > | > > | | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
@
@ <li><p>If a column of the result set is named "#" then that column
@ is assumed to hold a ticket number. A hyperlink will be created from
@ that column to a detailed view of the ticket.</p></li>
@
@ <li><p>If a column of the result set is named "bgcolor" then the content
@ of that column determines the background color of the row.</p></li>
@
@ <li><p>The text of all columns prior to the first column whose name begins
@ with underscore ("_") is shown character-for-character as it appears in
@ the database. In other words, it is assumed to have a mimetype of
@ text/plain.
@
@ <li><p>The first column whose name begins with underscore ("_") and all
@ subsequent columns are shown on their own rows in the table and with
@ wiki formatting. In other words, such rows are shown with a mimetype
@ of text/x-fossil-wiki. This is recommended for the "description" field
@ of tickets.
@ </p></li>
@
@ <li><p>The query can join other tables in the database besides TICKET.
@ </p></li>
@ </ul>
@
@ <h3>Examples</h3>
|
| ︙ | ︙ | |||
587 588 589 590 591 592 593 | @ owner AS 'By', @ subsystem AS 'Subsys', @ sdate(changetime) AS 'Changed', @ assignedto AS 'Assigned', @ severity AS 'Svr', @ priority AS 'Pri', @ title AS 'Title', | | | | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | @ owner AS 'By', @ subsystem AS 'Subsys', @ sdate(changetime) AS 'Changed', @ assignedto AS 'Assigned', @ severity AS 'Svr', @ priority AS 'Pri', @ title AS 'Title', @ description AS '_Description', -- When the column name begins with '_' @ remarks AS '_Remarks' -- content is rendered as wiki @ FROM ticket @ </pre></blockquote> @ @ <p>Or, to see part of the description on the same row, use the @ <b>wiki()</b> function with some string manipulation. Using the @ <b>tkt()</b> function on the ticket number will also generate a linked @ field, but without the extra <i>edit</i> column: |
| ︙ | ︙ | |||
726 727 728 729 730 731 732 |
if( pState->iNewRow>=0 && i>=pState->iNewRow ){
if( zTid && g.perm.Write ){
@ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
zTid = 0;
}
if( zData[0] ){
Blob content;
| > | | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 |
if( pState->iNewRow>=0 && i>=pState->iNewRow ){
if( zTid && g.perm.Write ){
@ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
zTid = 0;
}
if( zData[0] ){
Blob content;
@ </tr>
@ <tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)>
blob_init(&content, zData, -1);
wiki_convert(&content, 0, WIKI_NOBADLINKS);
blob_reset(&content);
}
}else if( azName[i][0]=='#' ){
zTid = zData;
@ <td valign="top">%z(href("%R/tktview?name=%h",zData))%h(zData)</a></td>
|
| ︙ | ︙ |
Changes to src/th_main.c.
| ︙ | ︙ | |||
70 71 72 73 74 75 76 |
static int enableOutputCmd(
Th_Interp *interp,
void *p,
int argc,
const char **argv,
int *argl
){
| > | | | > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
static int enableOutputCmd(
Th_Interp *interp,
void *p,
int argc,
const char **argv,
int *argl
){
int rc;
if( argc<2 || argc>3 ){
return Th_WrongNumArgs(interp, "enable_output [LABEL] BOOLEAN");
}
rc = Th_ToInt(interp, argv[argc-1], argl[argc-1], &enableOutput);
if( g.thTrace ){
Th_Trace("enable_output {%.*s} -> %d<br>\n", argl[1],argv[1],enableOutput);
}
return rc;
}
/*
** Return a name for a TH1 return code.
*/
const char *Th_ReturnCodeName(int rc){
static char zRc[32];
|
| ︙ | ︙ | |||
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
fflush(stdout);
}
if( encode ) free((char*)z);
}
}
static void sendError(const char *z, int n, int forceCgi){
if( forceCgi || g.cgiOutput ){
sendText("<hr><p class=\"thmainError\">", -1, 0);
}
sendText("ERROR: ", -1, 0);
sendText((char*)z, n, 1);
sendText(forceCgi || g.cgiOutput ? "</p>" : "\n", -1, 0);
}
/*
** TH command: puts STRING
** TH command: html STRING
**
** Output STRING escaped for HTML (html) or unchanged (puts).
| > > > | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
fflush(stdout);
}
if( encode ) free((char*)z);
}
}
static void sendError(const char *z, int n, int forceCgi){
int savedEnable = enableOutput;
enableOutput = 1;
if( forceCgi || g.cgiOutput ){
sendText("<hr><p class=\"thmainError\">", -1, 0);
}
sendText("ERROR: ", -1, 0);
sendText((char*)z, n, 1);
sendText(forceCgi || g.cgiOutput ? "</p>" : "\n", -1, 0);
enableOutput = savedEnable;
}
/*
** TH command: puts STRING
** TH command: html STRING
**
** Output STRING escaped for HTML (html) or unchanged (puts).
|
| ︙ | ︙ | |||
799 800 801 802 803 804 805 806 807 808 809 810 811 812 |
i = 0;
zResult = (char*)Th_GetResult(g.interp, &n);
sendText((char*)zResult, n, encode);
}else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){
sendText(z, i, 0);
z += i+5;
for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){}
rc = Th_Eval(g.interp, 0, (const char*)z, i);
if( rc!=TH_OK ) break;
z += i;
if( z[0] ){ z += 6; }
i = 0;
}else{
i++;
| > > > | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 |
i = 0;
zResult = (char*)Th_GetResult(g.interp, &n);
sendText((char*)zResult, n, encode);
}else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){
sendText(z, i, 0);
z += i+5;
for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){}
if( g.thTrace ){
Th_Trace("eval %d{<pre>%.*h</pre>}<br>", i, i, z);
}
rc = Th_Eval(g.interp, 0, (const char*)z, i);
if( rc!=TH_OK ) break;
z += i;
if( z[0] ){ z += 6; }
i = 0;
}else{
i++;
|
| ︙ | ︙ |
Changes to src/wikiformat.c.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 | #define ATTR_COLSPAN 10 #define ATTR_COMPACT 11 #define ATTR_FACE 12 #define ATTR_HEIGHT 13 #define ATTR_HREF 14 #define ATTR_HSPACE 15 #define ATTR_ID 16 | > | | | | | | | | | | | | > | | | | | | | | | | | | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#define ATTR_COLSPAN 10
#define ATTR_COMPACT 11
#define ATTR_FACE 12
#define ATTR_HEIGHT 13
#define ATTR_HREF 14
#define ATTR_HSPACE 15
#define ATTR_ID 16
#define ATTR_LINKS 17
#define ATTR_NAME 18
#define ATTR_ROWSPAN 19
#define ATTR_SIZE 20
#define ATTR_SRC 21
#define ATTR_START 22
#define ATTR_STYLE 23
#define ATTR_TARGET 24
#define ATTR_TYPE 25
#define ATTR_VALIGN 26
#define ATTR_VALUE 27
#define ATTR_VSPACE 28
#define ATTR_WIDTH 29
#define AMSK_ALIGN 0x00000001
#define AMSK_ALT 0x00000002
#define AMSK_BGCOLOR 0x00000004
#define AMSK_BORDER 0x00000008
#define AMSK_CELLPADDING 0x00000010
#define AMSK_CELLSPACING 0x00000020
#define AMSK_CLASS 0x00000040
#define AMSK_CLEAR 0x00000080
#define AMSK_COLOR 0x00000100
#define AMSK_COLSPAN 0x00000200
#define AMSK_COMPACT 0x00000400
#define AMSK_FACE 0x00000800
#define AMSK_HEIGHT 0x00001000
#define AMSK_HREF 0x00002000
#define AMSK_HSPACE 0x00004000
#define AMSK_ID 0x00008000
#define AMSK_LINKS 0x00010000
#define AMSK_NAME 0x00020000
#define AMSK_ROWSPAN 0x00040000
#define AMSK_SIZE 0x00080000
#define AMSK_SRC 0x00100000
#define AMSK_START 0x00200000
#define AMSK_STYLE 0x00400000
#define AMSK_TARGET 0x00800000
#define AMSK_TYPE 0x01000000
#define AMSK_VALIGN 0x02000000
#define AMSK_VALUE 0x04000000
#define AMSK_VSPACE 0x08000000
#define AMSK_WIDTH 0x10000000
static const struct AllowedAttribute {
const char *zName;
unsigned int iMask;
} aAttribute[] = {
{ 0, 0 },
{ "align", AMSK_ALIGN, },
|
| ︙ | ︙ | |||
111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
{ "colspan", AMSK_COLSPAN, },
{ "compact", AMSK_COMPACT, },
{ "face", AMSK_FACE, },
{ "height", AMSK_HEIGHT, },
{ "href", AMSK_HREF, },
{ "hspace", AMSK_HSPACE, },
{ "id", AMSK_ID, },
{ "name", AMSK_NAME, },
{ "rowspan", AMSK_ROWSPAN, },
{ "size", AMSK_SIZE, },
{ "src", AMSK_SRC, },
{ "start", AMSK_START, },
{ "style", AMSK_STYLE, },
{ "target", AMSK_TARGET, },
| > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
{ "colspan", AMSK_COLSPAN, },
{ "compact", AMSK_COMPACT, },
{ "face", AMSK_FACE, },
{ "height", AMSK_HEIGHT, },
{ "href", AMSK_HREF, },
{ "hspace", AMSK_HSPACE, },
{ "id", AMSK_ID, },
{ "links", AMSK_LINKS, },
{ "name", AMSK_NAME, },
{ "rowspan", AMSK_ROWSPAN, },
{ "size", AMSK_SIZE, },
{ "src", AMSK_SRC, },
{ "start", AMSK_START, },
{ "style", AMSK_STYLE, },
{ "target", AMSK_TARGET, },
|
| ︙ | ︙ | |||
436 437 438 439 440 441 442 |
*/
static int markupLength(const char *z){
int n = 1;
int inparen = 0;
int c;
if( z[n]=='/' ){ n++; }
if( !fossil_isalpha(z[n]) ) return 0;
| | | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 |
*/
static int markupLength(const char *z){
int n = 1;
int inparen = 0;
int c;
if( z[n]=='/' ){ n++; }
if( !fossil_isalpha(z[n]) ) return 0;
while( fossil_isalnum(z[n]) || z[n]=='-' ){ n++; }
c = z[n];
if( c=='/' && z[n+1]=='>' ){ return n+2; }
if( c!='>' && !fossil_isspace(c) ) return 0;
while( (c = z[n])!=0 && (c!='>' || inparen) ){
if( c==inparen ){
inparen = 0;
}else if( inparen==0 && (c=='"' || c=='\'') ){
|
| ︙ | ︙ | |||
748 749 750 751 752 753 754 755 |
if( j<sizeof(zTag)-1 ) zTag[j++] = fossil_tolower(z[i]);
i++;
}
zTag[j] = 0;
p->iCode = findTag(zTag);
p->iType = aMarkup[p->iCode].iType;
p->nAttr = 0;
while( fossil_isspace(z[i]) ){ i++; }
| > > > > > > > > > > > | | 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 |
if( j<sizeof(zTag)-1 ) zTag[j++] = fossil_tolower(z[i]);
i++;
}
zTag[j] = 0;
p->iCode = findTag(zTag);
p->iType = aMarkup[p->iCode].iType;
p->nAttr = 0;
c = 0;
if( z[i]=='-' ){
p->aAttr[0].iACode = iACode = ATTR_ID;
i++;
p->aAttr[0].zValue = &z[i];
while( fossil_isalnum(z[i]) ){ i++; }
p->aAttr[0].cTerm = c = z[i];
z[i++] = 0;
p->nAttr = 1;
if( c=='>' ) return;
}
while( fossil_isspace(z[i]) ){ i++; }
while( c!='>' && p->nAttr<8 && fossil_isalpha(z[i]) ){
int attrOk; /* True to preserver attribute. False to ignore it */
j = 0;
while( fossil_isalnum(z[i]) ){
if( j<sizeof(zTag)-1 ) zTag[j++] = fossil_tolower(z[i]);
i++;
}
zTag[j] = 0;
|
| ︙ | ︙ | |||
1431 1432 1433 1434 1435 1436 1437 |
}
case TOKEN_MARKUP: {
const char *zId;
int iDiv;
parseMarkup(&markup, z);
/* Markup of the form </div id=ID> where there is a matching
| | | < | 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 |
}
case TOKEN_MARKUP: {
const char *zId;
int iDiv;
parseMarkup(&markup, z);
/* Markup of the form </div id=ID> where there is a matching
** ID somewhere on the stack. Exit any contained verbatim.
** Pop the stack up to the matching <div>. Discard the </div>
*/
if( markup.iCode==MARKUP_DIV && markup.endTag &&
(zId = markupId(&markup))!=0 &&
(iDiv = findTagWithId(p, MARKUP_DIV, zId))>=0
){
if( p->inVerbatim ){
p->inVerbatim = 0;
|
| ︙ | ︙ | |||
1525 1526 1527 1528 1529 1530 1531 |
p->zVerbatimId = 0;
p->inVerbatim = 1;
p->preVerbState = p->state;
p->state &= ~ALLOW_WIKI;
for(ii=0; ii<markup.nAttr; ii++){
if( markup.aAttr[ii].iACode == ATTR_ID ){
p->zVerbatimId = markup.aAttr[ii].zValue;
| | < < < | | | < > > > | 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 |
p->zVerbatimId = 0;
p->inVerbatim = 1;
p->preVerbState = p->state;
p->state &= ~ALLOW_WIKI;
for(ii=0; ii<markup.nAttr; ii++){
if( markup.aAttr[ii].iACode == ATTR_ID ){
p->zVerbatimId = markup.aAttr[ii].zValue;
}else if( markup.aAttr[ii].iACode==ATTR_TYPE ){
blob_appendf(p->pOut, "<pre name='code' class='%s'>",
markup.aAttr[ii].zValue);
vAttrDidAppend=1;
}else if( markup.aAttr[ii].iACode==ATTR_LINKS
&& !is_false(markup.aAttr[ii].zValue) ){
p->state |= ALLOW_LINKS;
}
}
if( !vAttrDidAppend ) {
endAutoParagraph(p);
blob_append(p->pOut, "<pre class='verbatim'>",-1);
}
p->wantAutoParagraph = 0;
|
| ︙ | ︙ |