Fossil SCM

Improvements to the display of Wiki and Ticket changes.

drh 2012-10-31 23:07 UTC moderation
Commit ba0ae3b24aabfce510007c92b49fb6f6514be5fb
+86 -69
--- src/info.c
+++ src/info.c
@@ -713,84 +713,66 @@
713713
style_footer();
714714
}
715715
716716
/*
717717
** WEBPAGE: winfo
718
-** URL: /winfo?name=RID
718
+** URL: /winfo?name=UUID
719719
**
720720
** Return information about a wiki page.
721721
*/
722722
void winfo_page(void){
723
- Stmt q;
724723
int rid;
724
+ Manifest *pWiki;
725
+ char *zUuid;
726
+ char *zDate;
727
+ Blob wiki;
725728
726729
login_check_credentials();
727730
if( !g.perm.RdWiki ){ login_needed(); return; }
728731
rid = name_to_rid_www("name");
729
- if( rid==0 ){
732
+ if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI))==0 ){
730733
style_header("Wiki Page Information Error");
731
- @ No such object: %h(g.argv[2])
734
+ @ No such object: %h(P("name"))
732735
style_footer();
733736
return;
734737
}
735
- db_prepare(&q,
736
- "SELECT substr(tagname, 6, 1000), uuid,"
737
- " datetime(event.mtime, 'localtime'), user"
738
- " FROM tagxref, tag, blob, event"
739
- " WHERE tagxref.rid=%d"
740
- " AND tag.tagid=tagxref.tagid"
741
- " AND tag.tagname LIKE 'wiki-%%'"
742
- " AND blob.rid=%d"
743
- " AND event.objid=%d",
744
- rid, rid, rid
745
- );
746
- if( db_step(&q)==SQLITE_ROW ){
747
- const char *zName = db_column_text(&q, 0);
748
- const char *zUuid = db_column_text(&q, 1);
749
- char *zTitle = mprintf("Wiki Page %s", zName);
750
- const char *zDate = db_column_text(&q,2);
751
- const char *zUser = db_column_text(&q,3);
752
- style_header(zTitle);
753
- free(zTitle);
754
- login_anonymous_available();
755
- @ <div class="section">Overview</div>
756
- @ <p><table class="label-value">
757
- @ <tr><th>Version:</th><td>%s(zUuid)</td></tr>
758
- @ <tr><th>Date:</th><td>
759
- hyperlink_to_date(zDate, "</td></tr>");
760
- if( g.perm.Setup ){
761
- @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
762
- }
763
- @ <tr><th>Original&nbsp;User:</th><td>
764
- hyperlink_to_user(zUser, zDate, "</td></tr>");
765
- if( g.perm.Hyperlink ){
766
- @ <tr><th>Commands:</th>
767
- @ <td>
768
- @ %z(href("%R/whistory?name=%t",zName))history</a>
769
- @ | %z(href("%R/artifact/%S",zUuid))raw-text</a>
770
- @ </td>
771
- @ </tr>
772
- }
773
- @ </table></p>
774
- }else{
775
- style_header("Wiki Information");
776
- rid = 0;
777
- }
778
- db_finalize(&q);
779
- showTags(rid, "wiki-*");
780
- if( rid ){
781
- Manifest *pWiki;
782
- pWiki = manifest_get(rid, CFTYPE_WIKI);
783
- if( pWiki ){
784
- Blob wiki;
785
- blob_init(&wiki, pWiki->zWiki, -1);
786
- @ <div class="section">Content</div>
787
- wiki_convert(&wiki, 0, 0);
788
- blob_reset(&wiki);
789
- }
790
- manifest_destroy(pWiki);
791
- }
738
+ style_header("Edit To %h", pWiki->zWikiTitle);
739
+ zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
740
+ zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate);
741
+ style_submenu_element("Raw", "Raw", "artifact/%S", zUuid);
742
+ style_submenu_element("History", "History", "whistory?name=%t",
743
+ pWiki->zWikiTitle);
744
+ style_submenu_element("Page", "Page", "wiki?name=%t",
745
+ pWiki->zWikiTitle);
746
+ login_anonymous_available();
747
+ @ <div class="section">Overview</div>
748
+ @ <p><table class="label-value">
749
+ @ <tr><th>Artifact&nbsp;ID:</th><td>%s(zUuid)
750
+ if( g.perm.Setup ){
751
+ @ (%d(rid))
752
+ }
753
+ @ </td></tr>
754
+ @ <tr><th>Page&nbsp;Name:</th><td>%h(pWiki->zWikiTitle)</td></tr>
755
+ @ <tr><th>Date:</th><td>
756
+ hyperlink_to_date(zDate, "</td></tr>");
757
+ @ <tr><th>Original&nbsp;User:</th><td>
758
+ hyperlink_to_user(pWiki->zUser, zDate, "</td></tr>");
759
+ if( pWiki->nParent>0 ){
760
+ int i;
761
+ @ <tr><th>Parent%s(pWiki->nParent==1?"":"s"):</th><td>
762
+ for(i=0; i<pWiki->nParent; i++){
763
+ char *zParent = pWiki->azParent[i];
764
+ @ %z(href("info/%S",zParent))%s(zParent)</a>
765
+ }
766
+ @ </td></tr>
767
+ }
768
+ @ </table>
769
+ blob_init(&wiki, pWiki->zWiki, -1);
770
+ @ <div class="section">Content</div>
771
+ wiki_convert(&wiki, 0, 0);
772
+ blob_reset(&wiki);
773
+ manifest_destroy(pWiki);
792774
style_footer();
793775
}
794776
795777
/*
796778
** Show a webpage error message
@@ -993,10 +975,25 @@
993975
manifest_destroy(pTo);
994976
995977
style_footer();
996978
}
997979
980
+#if INTERFACE
981
+/*
982
+** Possible return values from object_description()
983
+*/
984
+#define OBJTYPE_CHECKIN 0x0001
985
+#define OBJTYPE_CONTENT 0x0002
986
+#define OBJTYPE_WIKI 0x0004
987
+#define OBJTYPE_TICKET 0x0008
988
+#define OBJTYPE_ATTACHMENT 0x0010
989
+#define OBJTYPE_EVENT 0x0020
990
+#define OBJTYPE_TAG 0x0040
991
+#define OBJTYPE_SYMLINK 0x0080
992
+#define OBJTYPE_EXE 0x0100
993
+#endif
994
+
998995
/*
999996
** Write a description of an object to the www reply.
1000997
**
1001998
** If the object is a file then mention:
1002999
**
@@ -1008,18 +1005,19 @@
10081005
**
10091006
** * It's artifact ID
10101007
** * date of check-in
10111008
** * Comment & user
10121009
*/
1013
-void object_description(
1010
+int object_description(
10141011
int rid, /* The artifact ID */
10151012
int linkToView, /* Add viewer link if true */
10161013
Blob *pDownloadName /* Fill with an appropriate download name */
10171014
){
10181015
Stmt q;
10191016
int cnt = 0;
10201017
int nWiki = 0;
1018
+ int objType = 0;
10211019
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
10221020
10231021
char *prevName = 0;
10241022
10251023
db_prepare(&q,
@@ -1051,15 +1049,18 @@
10511049
if( prevName ) {
10521050
@ </ul>
10531051
}
10541052
if( mPerm==PERM_LNK ){
10551053
@ <li>Symbolic link
1054
+ objType |= OBJTYPE_SYMLINK;
10561055
}else if( mPerm==PERM_EXE ){
10571056
@ <li>Executable file
1057
+ objType |= OBJTYPE_EXE;
10581058
}else{
10591059
@ <li>File
10601060
}
1061
+ objType |= OBJTYPE_CONTENT;
10611062
@ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
10621063
@ <ul>
10631064
prevName = fossil_strdup(zName);
10641065
}
10651066
@ <li>
@@ -1100,17 +1101,18 @@
11001101
if( cnt>0 ){
11011102
@ Also wiki page
11021103
}else{
11031104
@ Wiki page
11041105
}
1106
+ objType |= OBJTYPE_WIKI;
11051107
@ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by
11061108
hyperlink_to_user(zUser,zDate," on");
11071109
hyperlink_to_date(zDate,".");
11081110
nWiki++;
11091111
cnt++;
11101112
if( pDownloadName && blob_size(pDownloadName)==0 ){
1111
- blob_appendf(pDownloadName, "%s.wiki", zPagename);
1113
+ blob_appendf(pDownloadName, "%s.txt", zPagename);
11121114
}
11131115
}
11141116
db_finalize(&q);
11151117
if( nWiki==0 ){
11161118
db_prepare(&q,
@@ -1129,16 +1131,20 @@
11291131
if( cnt>0 ){
11301132
@ Also
11311133
}
11321134
if( zType[0]=='w' ){
11331135
@ Wiki edit
1136
+ objType |= OBJTYPE_WIKI;
11341137
}else if( zType[0]=='t' ){
11351138
@ Ticket change
1139
+ objType |= OBJTYPE_TICKET;
11361140
}else if( zType[0]=='c' ){
11371141
@ Manifest of check-in
1142
+ objType |= OBJTYPE_CHECKIN;
11381143
}else if( zType[0]=='e' ){
11391144
@ Instance of event
1145
+ objType |= OBJTYPE_EVENT;
11401146
hyperlink_to_event_tagid(db_column_int(&q, 5));
11411147
}else{
11421148
@ Control file referencing
11431149
}
11441150
if( zType[0]!='e' ){
@@ -1170,10 +1176,11 @@
11701176
if( cnt>0 ){
11711177
@ Also attachment "%h(zFilename)" to
11721178
}else{
11731179
@ Attachment "%h(zFilename)" to
11741180
}
1181
+ objType |= OBJTYPE_ATTACHMENT;
11751182
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
11761183
if( g.perm.Hyperlink && g.perm.RdTkt ){
11771184
@ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>]
11781185
}else{
11791186
@ ticket [%S(zTarget)]
@@ -1200,10 +1207,11 @@
12001207
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
12011208
}
12021209
}else if( linkToView && g.perm.Hyperlink ){
12031210
@ %z(href("%R/artifact/%S",zUuid))[view]</a>
12041211
}
1212
+ return objType;
12051213
}
12061214
12071215
12081216
/*
12091217
** WEBPAGE: fdiff
@@ -1519,11 +1527,15 @@
15191527
Blob content;
15201528
const char *zMime;
15211529
Blob downloadName;
15221530
int renderAsWiki = 0;
15231531
int renderAsHtml = 0;
1532
+ int objType;
1533
+ int asText;
15241534
const char *zUuid;
1535
+ Manifest *pManifest;
1536
+
15251537
if( P("ci") && P("filename") ){
15261538
rid = artifact_from_ci_and_filename();
15271539
}
15281540
if( rid==0 ){
15291541
rid = name_to_rid_www("name");
@@ -1544,35 +1556,39 @@
15441556
}
15451557
style_header("Artifact Content");
15461558
zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
15471559
@ <h2>Artifact %s(zUuid)</h2>
15481560
blob_zero(&downloadName);
1549
- object_description(rid, 0, &downloadName);
1561
+ objType = object_description(rid, 0, &downloadName);
15501562
style_submenu_element("Download", "Download",
15511563
"%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
1564
+ asText = P("txt")!=0;
15521565
zMime = mimetype_from_name(blob_str(&downloadName));
15531566
if( zMime ){
15541567
if( fossil_strcmp(zMime, "text/html")==0 ){
1555
- if( P("txt") ){
1568
+ if( asText ){
15561569
style_submenu_element("Html", "Html",
15571570
"%s/artifact/%s", g.zTop, zUuid);
15581571
}else{
15591572
renderAsHtml = 1;
15601573
style_submenu_element("Text", "Text",
15611574
"%s/artifact/%s?txt=1", g.zTop, zUuid);
15621575
}
15631576
}else if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
1564
- if( P("txt") ){
1577
+ if( asText ){
15651578
style_submenu_element("Wiki", "Wiki",
15661579
"%s/artifact/%s", g.zTop, zUuid);
15671580
}else{
15681581
renderAsWiki = 1;
15691582
style_submenu_element("Text", "Text",
15701583
"%s/artifact/%s?txt=1", g.zTop, zUuid);
15711584
}
15721585
}
15731586
}
1587
+ if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){
1588
+ style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid);
1589
+ }
15741590
@ <hr />
15751591
content_get(rid, &content);
15761592
if( renderAsWiki ){
15771593
wiki_convert(&content, 0, 0);
15781594
}else if( renderAsHtml ){
@@ -1643,13 +1659,14 @@
16431659
zTktName[10] = 0;
16441660
if( g.perm.Hyperlink ){
16451661
@ <h2>Changes to ticket
16461662
@ %z(href("%R/tktview/%s",pTktChng->zTicketUuid))%s(zTktName)</a></h2>
16471663
@
1648
- @ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
1649
- @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and
1650
- @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p>
1664
+ @ <p>By %h(pTktChng->zUser) on %s(zDate).
1665
+ style_submenu_element("Raw", "Raw", "%R/artifact/%T", zUuid);
1666
+ style_submenu_element("History", "History",
1667
+ "%R/tkthistory/%s", pTktChng->zTicketUuid);
16511668
}else{
16521669
@ <h2>Changes to ticket %s(zTktName)</h2>
16531670
@
16541671
@ <p>By %h(pTktChng->zUser) on %s(zDate).
16551672
@ </p>
16561673
--- src/info.c
+++ src/info.c
@@ -713,84 +713,66 @@
713 style_footer();
714 }
715
716 /*
717 ** WEBPAGE: winfo
718 ** URL: /winfo?name=RID
719 **
720 ** Return information about a wiki page.
721 */
722 void winfo_page(void){
723 Stmt q;
724 int rid;
 
 
 
 
725
726 login_check_credentials();
727 if( !g.perm.RdWiki ){ login_needed(); return; }
728 rid = name_to_rid_www("name");
729 if( rid==0 ){
730 style_header("Wiki Page Information Error");
731 @ No such object: %h(g.argv[2])
732 style_footer();
733 return;
734 }
735 db_prepare(&q,
736 "SELECT substr(tagname, 6, 1000), uuid,"
737 " datetime(event.mtime, 'localtime'), user"
738 " FROM tagxref, tag, blob, event"
739 " WHERE tagxref.rid=%d"
740 " AND tag.tagid=tagxref.tagid"
741 " AND tag.tagname LIKE 'wiki-%%'"
742 " AND blob.rid=%d"
743 " AND event.objid=%d",
744 rid, rid, rid
745 );
746 if( db_step(&q)==SQLITE_ROW ){
747 const char *zName = db_column_text(&q, 0);
748 const char *zUuid = db_column_text(&q, 1);
749 char *zTitle = mprintf("Wiki Page %s", zName);
750 const char *zDate = db_column_text(&q,2);
751 const char *zUser = db_column_text(&q,3);
752 style_header(zTitle);
753 free(zTitle);
754 login_anonymous_available();
755 @ <div class="section">Overview</div>
756 @ <p><table class="label-value">
757 @ <tr><th>Version:</th><td>%s(zUuid)</td></tr>
758 @ <tr><th>Date:</th><td>
759 hyperlink_to_date(zDate, "</td></tr>");
760 if( g.perm.Setup ){
761 @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
762 }
763 @ <tr><th>Original&nbsp;User:</th><td>
764 hyperlink_to_user(zUser, zDate, "</td></tr>");
765 if( g.perm.Hyperlink ){
766 @ <tr><th>Commands:</th>
767 @ <td>
768 @ %z(href("%R/whistory?name=%t",zName))history</a>
769 @ | %z(href("%R/artifact/%S",zUuid))raw-text</a>
770 @ </td>
771 @ </tr>
772 }
773 @ </table></p>
774 }else{
775 style_header("Wiki Information");
776 rid = 0;
777 }
778 db_finalize(&q);
779 showTags(rid, "wiki-*");
780 if( rid ){
781 Manifest *pWiki;
782 pWiki = manifest_get(rid, CFTYPE_WIKI);
783 if( pWiki ){
784 Blob wiki;
785 blob_init(&wiki, pWiki->zWiki, -1);
786 @ <div class="section">Content</div>
787 wiki_convert(&wiki, 0, 0);
788 blob_reset(&wiki);
789 }
790 manifest_destroy(pWiki);
791 }
792 style_footer();
793 }
794
795 /*
796 ** Show a webpage error message
@@ -993,10 +975,25 @@
993 manifest_destroy(pTo);
994
995 style_footer();
996 }
997
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
998 /*
999 ** Write a description of an object to the www reply.
1000 **
1001 ** If the object is a file then mention:
1002 **
@@ -1008,18 +1005,19 @@
1008 **
1009 ** * It's artifact ID
1010 ** * date of check-in
1011 ** * Comment & user
1012 */
1013 void object_description(
1014 int rid, /* The artifact ID */
1015 int linkToView, /* Add viewer link if true */
1016 Blob *pDownloadName /* Fill with an appropriate download name */
1017 ){
1018 Stmt q;
1019 int cnt = 0;
1020 int nWiki = 0;
 
1021 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1022
1023 char *prevName = 0;
1024
1025 db_prepare(&q,
@@ -1051,15 +1049,18 @@
1051 if( prevName ) {
1052 @ </ul>
1053 }
1054 if( mPerm==PERM_LNK ){
1055 @ <li>Symbolic link
 
1056 }else if( mPerm==PERM_EXE ){
1057 @ <li>Executable file
 
1058 }else{
1059 @ <li>File
1060 }
 
1061 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
1062 @ <ul>
1063 prevName = fossil_strdup(zName);
1064 }
1065 @ <li>
@@ -1100,17 +1101,18 @@
1100 if( cnt>0 ){
1101 @ Also wiki page
1102 }else{
1103 @ Wiki page
1104 }
 
1105 @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by
1106 hyperlink_to_user(zUser,zDate," on");
1107 hyperlink_to_date(zDate,".");
1108 nWiki++;
1109 cnt++;
1110 if( pDownloadName && blob_size(pDownloadName)==0 ){
1111 blob_appendf(pDownloadName, "%s.wiki", zPagename);
1112 }
1113 }
1114 db_finalize(&q);
1115 if( nWiki==0 ){
1116 db_prepare(&q,
@@ -1129,16 +1131,20 @@
1129 if( cnt>0 ){
1130 @ Also
1131 }
1132 if( zType[0]=='w' ){
1133 @ Wiki edit
 
1134 }else if( zType[0]=='t' ){
1135 @ Ticket change
 
1136 }else if( zType[0]=='c' ){
1137 @ Manifest of check-in
 
1138 }else if( zType[0]=='e' ){
1139 @ Instance of event
 
1140 hyperlink_to_event_tagid(db_column_int(&q, 5));
1141 }else{
1142 @ Control file referencing
1143 }
1144 if( zType[0]!='e' ){
@@ -1170,10 +1176,11 @@
1170 if( cnt>0 ){
1171 @ Also attachment "%h(zFilename)" to
1172 }else{
1173 @ Attachment "%h(zFilename)" to
1174 }
 
1175 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1176 if( g.perm.Hyperlink && g.perm.RdTkt ){
1177 @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>]
1178 }else{
1179 @ ticket [%S(zTarget)]
@@ -1200,10 +1207,11 @@
1200 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1201 }
1202 }else if( linkToView && g.perm.Hyperlink ){
1203 @ %z(href("%R/artifact/%S",zUuid))[view]</a>
1204 }
 
1205 }
1206
1207
1208 /*
1209 ** WEBPAGE: fdiff
@@ -1519,11 +1527,15 @@
1519 Blob content;
1520 const char *zMime;
1521 Blob downloadName;
1522 int renderAsWiki = 0;
1523 int renderAsHtml = 0;
 
 
1524 const char *zUuid;
 
 
1525 if( P("ci") && P("filename") ){
1526 rid = artifact_from_ci_and_filename();
1527 }
1528 if( rid==0 ){
1529 rid = name_to_rid_www("name");
@@ -1544,35 +1556,39 @@
1544 }
1545 style_header("Artifact Content");
1546 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1547 @ <h2>Artifact %s(zUuid)</h2>
1548 blob_zero(&downloadName);
1549 object_description(rid, 0, &downloadName);
1550 style_submenu_element("Download", "Download",
1551 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
 
1552 zMime = mimetype_from_name(blob_str(&downloadName));
1553 if( zMime ){
1554 if( fossil_strcmp(zMime, "text/html")==0 ){
1555 if( P("txt") ){
1556 style_submenu_element("Html", "Html",
1557 "%s/artifact/%s", g.zTop, zUuid);
1558 }else{
1559 renderAsHtml = 1;
1560 style_submenu_element("Text", "Text",
1561 "%s/artifact/%s?txt=1", g.zTop, zUuid);
1562 }
1563 }else if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
1564 if( P("txt") ){
1565 style_submenu_element("Wiki", "Wiki",
1566 "%s/artifact/%s", g.zTop, zUuid);
1567 }else{
1568 renderAsWiki = 1;
1569 style_submenu_element("Text", "Text",
1570 "%s/artifact/%s?txt=1", g.zTop, zUuid);
1571 }
1572 }
1573 }
 
 
 
1574 @ <hr />
1575 content_get(rid, &content);
1576 if( renderAsWiki ){
1577 wiki_convert(&content, 0, 0);
1578 }else if( renderAsHtml ){
@@ -1643,13 +1659,14 @@
1643 zTktName[10] = 0;
1644 if( g.perm.Hyperlink ){
1645 @ <h2>Changes to ticket
1646 @ %z(href("%R/tktview/%s",pTktChng->zTicketUuid))%s(zTktName)</a></h2>
1647 @
1648 @ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
1649 @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and
1650 @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p>
 
1651 }else{
1652 @ <h2>Changes to ticket %s(zTktName)</h2>
1653 @
1654 @ <p>By %h(pTktChng->zUser) on %s(zDate).
1655 @ </p>
1656
--- src/info.c
+++ src/info.c
@@ -713,84 +713,66 @@
713 style_footer();
714 }
715
716 /*
717 ** WEBPAGE: winfo
718 ** URL: /winfo?name=UUID
719 **
720 ** Return information about a wiki page.
721 */
722 void winfo_page(void){
 
723 int rid;
724 Manifest *pWiki;
725 char *zUuid;
726 char *zDate;
727 Blob wiki;
728
729 login_check_credentials();
730 if( !g.perm.RdWiki ){ login_needed(); return; }
731 rid = name_to_rid_www("name");
732 if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI))==0 ){
733 style_header("Wiki Page Information Error");
734 @ No such object: %h(P("name"))
735 style_footer();
736 return;
737 }
738 style_header("Edit To %h", pWiki->zWikiTitle);
739 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
740 zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate);
741 style_submenu_element("Raw", "Raw", "artifact/%S", zUuid);
742 style_submenu_element("History", "History", "whistory?name=%t",
743 pWiki->zWikiTitle);
744 style_submenu_element("Page", "Page", "wiki?name=%t",
745 pWiki->zWikiTitle);
746 login_anonymous_available();
747 @ <div class="section">Overview</div>
748 @ <p><table class="label-value">
749 @ <tr><th>Artifact&nbsp;ID:</th><td>%s(zUuid)
750 if( g.perm.Setup ){
751 @ (%d(rid))
752 }
753 @ </td></tr>
754 @ <tr><th>Page&nbsp;Name:</th><td>%h(pWiki->zWikiTitle)</td></tr>
755 @ <tr><th>Date:</th><td>
756 hyperlink_to_date(zDate, "</td></tr>");
757 @ <tr><th>Original&nbsp;User:</th><td>
758 hyperlink_to_user(pWiki->zUser, zDate, "</td></tr>");
759 if( pWiki->nParent>0 ){
760 int i;
761 @ <tr><th>Parent%s(pWiki->nParent==1?"":"s"):</th><td>
762 for(i=0; i<pWiki->nParent; i++){
763 char *zParent = pWiki->azParent[i];
764 @ %z(href("info/%S",zParent))%s(zParent)</a>
765 }
766 @ </td></tr>
767 }
768 @ </table>
769 blob_init(&wiki, pWiki->zWiki, -1);
770 @ <div class="section">Content</div>
771 wiki_convert(&wiki, 0, 0);
772 blob_reset(&wiki);
773 manifest_destroy(pWiki);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774 style_footer();
775 }
776
777 /*
778 ** Show a webpage error message
@@ -993,10 +975,25 @@
975 manifest_destroy(pTo);
976
977 style_footer();
978 }
979
980 #if INTERFACE
981 /*
982 ** Possible return values from object_description()
983 */
984 #define OBJTYPE_CHECKIN 0x0001
985 #define OBJTYPE_CONTENT 0x0002
986 #define OBJTYPE_WIKI 0x0004
987 #define OBJTYPE_TICKET 0x0008
988 #define OBJTYPE_ATTACHMENT 0x0010
989 #define OBJTYPE_EVENT 0x0020
990 #define OBJTYPE_TAG 0x0040
991 #define OBJTYPE_SYMLINK 0x0080
992 #define OBJTYPE_EXE 0x0100
993 #endif
994
995 /*
996 ** Write a description of an object to the www reply.
997 **
998 ** If the object is a file then mention:
999 **
@@ -1008,18 +1005,19 @@
1005 **
1006 ** * It's artifact ID
1007 ** * date of check-in
1008 ** * Comment & user
1009 */
1010 int object_description(
1011 int rid, /* The artifact ID */
1012 int linkToView, /* Add viewer link if true */
1013 Blob *pDownloadName /* Fill with an appropriate download name */
1014 ){
1015 Stmt q;
1016 int cnt = 0;
1017 int nWiki = 0;
1018 int objType = 0;
1019 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1020
1021 char *prevName = 0;
1022
1023 db_prepare(&q,
@@ -1051,15 +1049,18 @@
1049 if( prevName ) {
1050 @ </ul>
1051 }
1052 if( mPerm==PERM_LNK ){
1053 @ <li>Symbolic link
1054 objType |= OBJTYPE_SYMLINK;
1055 }else if( mPerm==PERM_EXE ){
1056 @ <li>Executable file
1057 objType |= OBJTYPE_EXE;
1058 }else{
1059 @ <li>File
1060 }
1061 objType |= OBJTYPE_CONTENT;
1062 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
1063 @ <ul>
1064 prevName = fossil_strdup(zName);
1065 }
1066 @ <li>
@@ -1100,17 +1101,18 @@
1101 if( cnt>0 ){
1102 @ Also wiki page
1103 }else{
1104 @ Wiki page
1105 }
1106 objType |= OBJTYPE_WIKI;
1107 @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by
1108 hyperlink_to_user(zUser,zDate," on");
1109 hyperlink_to_date(zDate,".");
1110 nWiki++;
1111 cnt++;
1112 if( pDownloadName && blob_size(pDownloadName)==0 ){
1113 blob_appendf(pDownloadName, "%s.txt", zPagename);
1114 }
1115 }
1116 db_finalize(&q);
1117 if( nWiki==0 ){
1118 db_prepare(&q,
@@ -1129,16 +1131,20 @@
1131 if( cnt>0 ){
1132 @ Also
1133 }
1134 if( zType[0]=='w' ){
1135 @ Wiki edit
1136 objType |= OBJTYPE_WIKI;
1137 }else if( zType[0]=='t' ){
1138 @ Ticket change
1139 objType |= OBJTYPE_TICKET;
1140 }else if( zType[0]=='c' ){
1141 @ Manifest of check-in
1142 objType |= OBJTYPE_CHECKIN;
1143 }else if( zType[0]=='e' ){
1144 @ Instance of event
1145 objType |= OBJTYPE_EVENT;
1146 hyperlink_to_event_tagid(db_column_int(&q, 5));
1147 }else{
1148 @ Control file referencing
1149 }
1150 if( zType[0]!='e' ){
@@ -1170,10 +1176,11 @@
1176 if( cnt>0 ){
1177 @ Also attachment "%h(zFilename)" to
1178 }else{
1179 @ Attachment "%h(zFilename)" to
1180 }
1181 objType |= OBJTYPE_ATTACHMENT;
1182 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1183 if( g.perm.Hyperlink && g.perm.RdTkt ){
1184 @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>]
1185 }else{
1186 @ ticket [%S(zTarget)]
@@ -1200,10 +1207,11 @@
1207 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1208 }
1209 }else if( linkToView && g.perm.Hyperlink ){
1210 @ %z(href("%R/artifact/%S",zUuid))[view]</a>
1211 }
1212 return objType;
1213 }
1214
1215
1216 /*
1217 ** WEBPAGE: fdiff
@@ -1519,11 +1527,15 @@
1527 Blob content;
1528 const char *zMime;
1529 Blob downloadName;
1530 int renderAsWiki = 0;
1531 int renderAsHtml = 0;
1532 int objType;
1533 int asText;
1534 const char *zUuid;
1535 Manifest *pManifest;
1536
1537 if( P("ci") && P("filename") ){
1538 rid = artifact_from_ci_and_filename();
1539 }
1540 if( rid==0 ){
1541 rid = name_to_rid_www("name");
@@ -1544,35 +1556,39 @@
1556 }
1557 style_header("Artifact Content");
1558 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1559 @ <h2>Artifact %s(zUuid)</h2>
1560 blob_zero(&downloadName);
1561 objType = object_description(rid, 0, &downloadName);
1562 style_submenu_element("Download", "Download",
1563 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
1564 asText = P("txt")!=0;
1565 zMime = mimetype_from_name(blob_str(&downloadName));
1566 if( zMime ){
1567 if( fossil_strcmp(zMime, "text/html")==0 ){
1568 if( asText ){
1569 style_submenu_element("Html", "Html",
1570 "%s/artifact/%s", g.zTop, zUuid);
1571 }else{
1572 renderAsHtml = 1;
1573 style_submenu_element("Text", "Text",
1574 "%s/artifact/%s?txt=1", g.zTop, zUuid);
1575 }
1576 }else if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
1577 if( asText ){
1578 style_submenu_element("Wiki", "Wiki",
1579 "%s/artifact/%s", g.zTop, zUuid);
1580 }else{
1581 renderAsWiki = 1;
1582 style_submenu_element("Text", "Text",
1583 "%s/artifact/%s?txt=1", g.zTop, zUuid);
1584 }
1585 }
1586 }
1587 if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){
1588 style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid);
1589 }
1590 @ <hr />
1591 content_get(rid, &content);
1592 if( renderAsWiki ){
1593 wiki_convert(&content, 0, 0);
1594 }else if( renderAsHtml ){
@@ -1643,13 +1659,14 @@
1659 zTktName[10] = 0;
1660 if( g.perm.Hyperlink ){
1661 @ <h2>Changes to ticket
1662 @ %z(href("%R/tktview/%s",pTktChng->zTicketUuid))%s(zTktName)</a></h2>
1663 @
1664 @ <p>By %h(pTktChng->zUser) on %s(zDate).
1665 style_submenu_element("Raw", "Raw", "%R/artifact/%T", zUuid);
1666 style_submenu_element("History", "History",
1667 "%R/tkthistory/%s", pTktChng->zTicketUuid);
1668 }else{
1669 @ <h2>Changes to ticket %s(zTktName)</h2>
1670 @
1671 @ <p>By %h(pTktChng->zUser) on %s(zDate).
1672 @ </p>
1673
+6 -4
--- src/manifest.c
+++ src/manifest.c
@@ -318,20 +318,22 @@
318318
** Parse a blob into a Manifest object. The Manifest object
319319
** takes over the input blob and will free it when the
320320
** Manifest object is freed. Zeros are inserted into the blob
321321
** as string terminators so that blob should not be used again.
322322
**
323
-** Return TRUE if the content really is a control file of some
324
-** kind. Return FALSE if there are syntax errors.
323
+** Return a pointer to an allocated Manifest object if the content
324
+** really is a control file of some kind. This object needs to be
325
+** freed by a subsequent call to manifest_destroy(). Return NULL
326
+** if there are syntax errors.
325327
**
326328
** This routine is strict about the format of a control file.
327329
** The format must match exactly or else it is rejected. This
328330
** rule minimizes the risk that a content file will be mistaken
329331
** for a control file simply because they look the same.
330332
**
331
-** The pContent is reset. If TRUE is returned, then pContent will
332
-** be reset when the Manifest object is cleared. If FALSE is
333
+** The pContent is reset. If a pointer is returned, then pContent will
334
+** be reset when the Manifest object is cleared. If NULL is
333335
** returned then the Manifest object is cleared automatically
334336
** and pContent is reset before the return.
335337
**
336338
** The entire file can be PGP clear-signed. The signature is ignored.
337339
** The file consists of zero or more cards, one card per line.
338340
--- src/manifest.c
+++ src/manifest.c
@@ -318,20 +318,22 @@
318 ** Parse a blob into a Manifest object. The Manifest object
319 ** takes over the input blob and will free it when the
320 ** Manifest object is freed. Zeros are inserted into the blob
321 ** as string terminators so that blob should not be used again.
322 **
323 ** Return TRUE if the content really is a control file of some
324 ** kind. Return FALSE if there are syntax errors.
 
 
325 **
326 ** This routine is strict about the format of a control file.
327 ** The format must match exactly or else it is rejected. This
328 ** rule minimizes the risk that a content file will be mistaken
329 ** for a control file simply because they look the same.
330 **
331 ** The pContent is reset. If TRUE is returned, then pContent will
332 ** be reset when the Manifest object is cleared. If FALSE is
333 ** returned then the Manifest object is cleared automatically
334 ** and pContent is reset before the return.
335 **
336 ** The entire file can be PGP clear-signed. The signature is ignored.
337 ** The file consists of zero or more cards, one card per line.
338
--- src/manifest.c
+++ src/manifest.c
@@ -318,20 +318,22 @@
318 ** Parse a blob into a Manifest object. The Manifest object
319 ** takes over the input blob and will free it when the
320 ** Manifest object is freed. Zeros are inserted into the blob
321 ** as string terminators so that blob should not be used again.
322 **
323 ** Return a pointer to an allocated Manifest object if the content
324 ** really is a control file of some kind. This object needs to be
325 ** freed by a subsequent call to manifest_destroy(). Return NULL
326 ** if there are syntax errors.
327 **
328 ** This routine is strict about the format of a control file.
329 ** The format must match exactly or else it is rejected. This
330 ** rule minimizes the risk that a content file will be mistaken
331 ** for a control file simply because they look the same.
332 **
333 ** The pContent is reset. If a pointer is returned, then pContent will
334 ** be reset when the Manifest object is cleared. If NULL is
335 ** returned then the Manifest object is cleared automatically
336 ** and pContent is reset before the return.
337 **
338 ** The entire file can be PGP clear-signed. The signature is ignored.
339 ** The file consists of zero or more cards, one card per line.
340
+4 -4
--- src/moderate.c
+++ src/moderate.c
@@ -29,15 +29,15 @@
2929
*/
3030
void moderation_table_create(void){
3131
db_multi_exec(
3232
"CREATE TABLE IF NOT EXISTS modreq("
3333
" mreqid INTEGER PRIMARY KEY," /* Unique ID for the request */
34
- " ctime DATE," /* Julian day number */
34
+ " objid INT UNIQUE," /* Record pending approval */
35
+ " ctime DATETIME," /* Julian day number */
3536
" user TEXT," /* Name of user submitter */
3637
" ipaddr TEXT," /* IP address of submitter */
37
- " mtype CHAR(1)," /* 't', 'w', or 'a' */
38
- " rid INT," /* Record pending approval */
38
+ " mtype TEXT," /* 't', 'w', 'at', or 'aw' */
3939
" afile INT," /* File being attached, or NULL */
40
- " objid ANY" /* TicketId or Wiki Name */
40
+ " aid ANY" /* TicketId or Wiki Name */
4141
");"
4242
);
4343
}
4444
--- src/moderate.c
+++ src/moderate.c
@@ -29,15 +29,15 @@
29 */
30 void moderation_table_create(void){
31 db_multi_exec(
32 "CREATE TABLE IF NOT EXISTS modreq("
33 " mreqid INTEGER PRIMARY KEY," /* Unique ID for the request */
34 " ctime DATE," /* Julian day number */
 
35 " user TEXT," /* Name of user submitter */
36 " ipaddr TEXT," /* IP address of submitter */
37 " mtype CHAR(1)," /* 't', 'w', or 'a' */
38 " rid INT," /* Record pending approval */
39 " afile INT," /* File being attached, or NULL */
40 " objid ANY" /* TicketId or Wiki Name */
41 ");"
42 );
43 }
44
--- src/moderate.c
+++ src/moderate.c
@@ -29,15 +29,15 @@
29 */
30 void moderation_table_create(void){
31 db_multi_exec(
32 "CREATE TABLE IF NOT EXISTS modreq("
33 " mreqid INTEGER PRIMARY KEY," /* Unique ID for the request */
34 " objid INT UNIQUE," /* Record pending approval */
35 " ctime DATETIME," /* Julian day number */
36 " user TEXT," /* Name of user submitter */
37 " ipaddr TEXT," /* IP address of submitter */
38 " mtype TEXT," /* 't', 'w', 'at', or 'aw' */
 
39 " afile INT," /* File being attached, or NULL */
40 " aid ANY" /* TicketId or Wiki Name */
41 ");"
42 );
43 }
44
+4 -1
--- src/wiki.c
+++ src/wiki.c
@@ -240,11 +240,14 @@
240240
@ %h(zFile)
241241
}
242242
@ added by %h(zUser) on
243243
hyperlink_to_date(zDate, ".");
244244
if( g.perm.WrWiki && g.perm.Attach ){
245
- @ [%z(href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>]
245
+ char *zH;
246
+ zH = href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",
247
+ zPageName, zFile, zPageName);
248
+ @ [%z(zH)delete</a>]
246249
}
247250
@ </li>
248251
}
249252
if( cnt ){
250253
@ </ul>
251254
--- src/wiki.c
+++ src/wiki.c
@@ -240,11 +240,14 @@
240 @ %h(zFile)
241 }
242 @ added by %h(zUser) on
243 hyperlink_to_date(zDate, ".");
244 if( g.perm.WrWiki && g.perm.Attach ){
245 @ [%z(href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>]
 
 
 
246 }
247 @ </li>
248 }
249 if( cnt ){
250 @ </ul>
251
--- src/wiki.c
+++ src/wiki.c
@@ -240,11 +240,14 @@
240 @ %h(zFile)
241 }
242 @ added by %h(zUser) on
243 hyperlink_to_date(zDate, ".");
244 if( g.perm.WrWiki && g.perm.Attach ){
245 char *zH;
246 zH = href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",
247 zPageName, zFile, zPageName);
248 @ [%z(zH)delete</a>]
249 }
250 @ </li>
251 }
252 if( cnt ){
253 @ </ul>
254

Keyboard Shortcuts

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