Fossil SCM

The "h" capability is now used to enable hyperlinks to non-wiki pages. When "h" is missing, many pages give a hyperlink to the login page and automatically fill in "anonymous" as the user name. The login page jumps back to the target page after a successful login.

drh 2008-05-05 23:15 trunk
Commit d57de28756ddf7716d08a04ebfe1f5f2fd8c7687
+2 -2
--- src/browse.c
+++ src/browse.c
@@ -83,15 +83,15 @@
8383
int i, j;
8484
char *zSep = "";
8585
8686
for(i=0; zPath[i]; i=j){
8787
for(j=i; zPath[j] && zPath[j]!='/'; j++){}
88
- if( zPath[j] ){
88
+ if( zPath[j] && g.okHistory ){
8989
blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
9090
zSep, g.zBaseURL, j, zPath, j-i, &zPath[i]);
9191
}else{
92
- blob_appendf(pOut, "%s%h", zSep, &zPath[i]);
92
+ blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
9393
}
9494
zSep = "/";
9595
while( zPath[j]=='/' ){ j++; }
9696
}
9797
}
9898
--- src/browse.c
+++ src/browse.c
@@ -83,15 +83,15 @@
83 int i, j;
84 char *zSep = "";
85
86 for(i=0; zPath[i]; i=j){
87 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
88 if( zPath[j] ){
89 blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
90 zSep, g.zBaseURL, j, zPath, j-i, &zPath[i]);
91 }else{
92 blob_appendf(pOut, "%s%h", zSep, &zPath[i]);
93 }
94 zSep = "/";
95 while( zPath[j]=='/' ){ j++; }
96 }
97 }
98
--- src/browse.c
+++ src/browse.c
@@ -83,15 +83,15 @@
83 int i, j;
84 char *zSep = "";
85
86 for(i=0; zPath[i]; i=j){
87 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
88 if( zPath[j] && g.okHistory ){
89 blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
90 zSep, g.zBaseURL, j, zPath, j-i, &zPath[i]);
91 }else{
92 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
93 }
94 zSep = "/";
95 while( zPath[j]=='/' ){ j++; }
96 }
97 }
98
+15 -5
--- src/db.c
+++ src/db.c
@@ -1151,15 +1151,17 @@
11511151
){
11521152
const char *zUuid; /* The UUID to render */
11531153
char *z; /* Rendered HTML text */
11541154
11551155
zUuid = (const char*)sqlite3_value_text(argv[0]);
1156
- if( zUuid && strlen(zUuid)>=10 ){
1156
+ if( g.okHistory && zUuid && strlen(zUuid)>=10 ){
11571157
z = mprintf("<tt><a href='%s/vinfo/%t'><span style='font-size:1.5em'>"
11581158
"%#h</span>%h</a></tt>",
11591159
g.zBaseURL, zUuid, 10, zUuid, &zUuid[10]);
11601160
sqlite3_result_text(pCxt, z, -1, free);
1161
+ }else{
1162
+ sqlite3_result_text(pCxt, zUuid, -1, SQLITE_TRANSIENT);
11611163
}
11621164
}
11631165
11641166
/*
11651167
** SQL function to render a TAGID as a hyperlink to a page describing
@@ -1172,12 +1174,16 @@
11721174
){
11731175
int tagid; /* The tagid to render */
11741176
char *z; /* rendered html text */
11751177
11761178
tagid = sqlite3_value_int(argv[0]);
1177
- z = mprintf("<a href='%s/tagview?tagid=%d'>%d</a>",
1178
- g.zBaseURL, tagid, tagid);
1179
+ if( g.okHistory ){
1180
+ z = mprintf("<a href='%s/tagview?tagid=%d'>%d</a>",
1181
+ g.zBaseURL, tagid, tagid);
1182
+ }else{
1183
+ z = mprintf("%d", tagid);
1184
+ }
11791185
sqlite3_result_text(pCxt, z, -1, free);
11801186
}
11811187
11821188
/*
11831189
** SQL function to render a TAGNAME as a hyperlink to a page describing
@@ -1190,12 +1196,16 @@
11901196
){
11911197
const char *zTag; /* The tag to render */
11921198
char *z; /* rendered html text */
11931199
11941200
zTag = (const char*)sqlite3_value_text(argv[0]);
1195
- z = mprintf("<a href='%s/tagview?name=%T'>%h</a>",
1196
- g.zBaseURL, zTag, zTag);
1201
+ if( g.okHistory ){
1202
+ z = mprintf("<a href='%s/tagview?name=%T'>%h</a>",
1203
+ g.zBaseURL, zTag, zTag);
1204
+ }else{
1205
+ z = mprintf("%h", zTag);
1206
+ }
11971207
sqlite3_result_text(pCxt, z, -1, free);
11981208
}
11991209
12001210
/*
12011211
** SQL function to escape all characters in a string that have special
12021212
--- src/db.c
+++ src/db.c
@@ -1151,15 +1151,17 @@
1151 ){
1152 const char *zUuid; /* The UUID to render */
1153 char *z; /* Rendered HTML text */
1154
1155 zUuid = (const char*)sqlite3_value_text(argv[0]);
1156 if( zUuid && strlen(zUuid)>=10 ){
1157 z = mprintf("<tt><a href='%s/vinfo/%t'><span style='font-size:1.5em'>"
1158 "%#h</span>%h</a></tt>",
1159 g.zBaseURL, zUuid, 10, zUuid, &zUuid[10]);
1160 sqlite3_result_text(pCxt, z, -1, free);
 
 
1161 }
1162 }
1163
1164 /*
1165 ** SQL function to render a TAGID as a hyperlink to a page describing
@@ -1172,12 +1174,16 @@
1172 ){
1173 int tagid; /* The tagid to render */
1174 char *z; /* rendered html text */
1175
1176 tagid = sqlite3_value_int(argv[0]);
1177 z = mprintf("<a href='%s/tagview?tagid=%d'>%d</a>",
1178 g.zBaseURL, tagid, tagid);
 
 
 
 
1179 sqlite3_result_text(pCxt, z, -1, free);
1180 }
1181
1182 /*
1183 ** SQL function to render a TAGNAME as a hyperlink to a page describing
@@ -1190,12 +1196,16 @@
1190 ){
1191 const char *zTag; /* The tag to render */
1192 char *z; /* rendered html text */
1193
1194 zTag = (const char*)sqlite3_value_text(argv[0]);
1195 z = mprintf("<a href='%s/tagview?name=%T'>%h</a>",
1196 g.zBaseURL, zTag, zTag);
 
 
 
 
1197 sqlite3_result_text(pCxt, z, -1, free);
1198 }
1199
1200 /*
1201 ** SQL function to escape all characters in a string that have special
1202
--- src/db.c
+++ src/db.c
@@ -1151,15 +1151,17 @@
1151 ){
1152 const char *zUuid; /* The UUID to render */
1153 char *z; /* Rendered HTML text */
1154
1155 zUuid = (const char*)sqlite3_value_text(argv[0]);
1156 if( g.okHistory && zUuid && strlen(zUuid)>=10 ){
1157 z = mprintf("<tt><a href='%s/vinfo/%t'><span style='font-size:1.5em'>"
1158 "%#h</span>%h</a></tt>",
1159 g.zBaseURL, zUuid, 10, zUuid, &zUuid[10]);
1160 sqlite3_result_text(pCxt, z, -1, free);
1161 }else{
1162 sqlite3_result_text(pCxt, zUuid, -1, SQLITE_TRANSIENT);
1163 }
1164 }
1165
1166 /*
1167 ** SQL function to render a TAGID as a hyperlink to a page describing
@@ -1172,12 +1174,16 @@
1174 ){
1175 int tagid; /* The tagid to render */
1176 char *z; /* rendered html text */
1177
1178 tagid = sqlite3_value_int(argv[0]);
1179 if( g.okHistory ){
1180 z = mprintf("<a href='%s/tagview?tagid=%d'>%d</a>",
1181 g.zBaseURL, tagid, tagid);
1182 }else{
1183 z = mprintf("%d", tagid);
1184 }
1185 sqlite3_result_text(pCxt, z, -1, free);
1186 }
1187
1188 /*
1189 ** SQL function to render a TAGNAME as a hyperlink to a page describing
@@ -1190,12 +1196,16 @@
1196 ){
1197 const char *zTag; /* The tag to render */
1198 char *z; /* rendered html text */
1199
1200 zTag = (const char*)sqlite3_value_text(argv[0]);
1201 if( g.okHistory ){
1202 z = mprintf("<a href='%s/tagview?name=%T'>%h</a>",
1203 g.zBaseURL, zTag, zTag);
1204 }else{
1205 z = mprintf("%h", zTag);
1206 }
1207 sqlite3_result_text(pCxt, z, -1, free);
1208 }
1209
1210 /*
1211 ** SQL function to escape all characters in a string that have special
1212
--- src/descendents.c
+++ src/descendents.c
@@ -189,10 +189,11 @@
189189
190190
login_check_credentials();
191191
if( !g.okRead ){ login_needed(); return; }
192192
193193
style_header("Leaves");
194
+ login_anonymous_available();
194195
db_prepare(&q,
195196
"%s"
196197
" AND blob.rid IN"
197198
" (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
198199
" ORDER BY event.mtime DESC",
199200
--- src/descendents.c
+++ src/descendents.c
@@ -189,10 +189,11 @@
189
190 login_check_credentials();
191 if( !g.okRead ){ login_needed(); return; }
192
193 style_header("Leaves");
 
194 db_prepare(&q,
195 "%s"
196 " AND blob.rid IN"
197 " (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
198 " ORDER BY event.mtime DESC",
199
--- src/descendents.c
+++ src/descendents.c
@@ -189,10 +189,11 @@
189
190 login_check_credentials();
191 if( !g.okRead ){ login_needed(); return; }
192
193 style_header("Leaves");
194 login_anonymous_available();
195 db_prepare(&q,
196 "%s"
197 " AND blob.rid IN"
198 " (SELECT cid FROM plink EXCEPT SELECT pid FROM plink)"
199 " ORDER BY event.mtime DESC",
200
+27 -15
--- src/login.c
+++ src/login.c
@@ -74,17 +74,19 @@
7474
** Generate the login page
7575
*/
7676
void login_page(void){
7777
const char *zUsername, *zPasswd, *zGoto;
7878
const char *zNew1, *zNew2;
79
- const char *zAnonPw;
79
+ const char *zAnonPw = 0;
80
+ int anonFlag;
8081
char *zErrMsg = "";
8182
8283
login_check_credentials();
8384
zUsername = P("u");
8485
zPasswd = P("p");
8586
zGoto = PD("g","index");
87
+ anonFlag = P("anon")!=0;
8688
if( P("out")!=0 ){
8789
const char *zCookieName = login_cookie_name();
8890
cgi_set_cookie(zCookieName, "", 0, -86400);
8991
cgi_redirect(zGoto);
9092
}
@@ -147,21 +149,35 @@
147149
}
148150
style_header("Login/Logout");
149151
@ %s(zErrMsg)
150152
@ <form action="login" method="POST">
151153
if( P("g") ){
152
- @ <input type="hidden" name="nxp" value="%h(P("g"))">
154
+ @ <input type="hidden" name="g" value="%h(P("g"))">
153155
}
154156
@ <table align="left" hspace="10">
155157
@ <tr>
156158
@ <td align="right">User ID:</td>
157
- @ <td><input type="text" name="u" value="" size=30></td>
159
+ if( anonFlag ){
160
+ @ <td><input type="text" name="u" value="anonymous" size=30></td>
161
+ }else{
162
+ @ <td><input type="text" name="u" value="" size=30></td>
163
+ }
158164
@ </tr>
159165
@ <tr>
160166
@ <td align="right">Password:</td>
161167
@ <td><input type="password" name="p" value="" size=30></td>
162168
@ </tr>
169
+ if( g.zLogin==0 ){
170
+ zAnonPw = db_text(0, "SELECT pw FROM user"
171
+ " WHERE login='anonymous'"
172
+ " AND cap!=''");
173
+ if( zAnonPw && anonFlag ){
174
+ @ <tr><td></td>
175
+ @ <td>The anonymous password is "<b>%h(zAnonPw)</b>".</td>
176
+ @ </tr>
177
+ }
178
+ }
163179
@ <tr>
164180
@ <td></td>
165181
@ <td><input type="submit" name="in" value="Login"></td>
166182
@ </tr>
167183
@ </table>
@@ -174,19 +190,15 @@
174190
@ enter the user-id and password at the left and press the
175191
@ "Login" button. Your user name will be stored in a browser cookie.
176192
@ You must configure your web browser to accept cookies in order for
177193
@ the login to take.</p>
178194
if( g.zLogin==0 ){
179
- zAnonPw = db_text(0, "SELECT pw FROM user"
180
- " WHERE login='anonymous'"
181
- " AND cap!=''");
182
- if( zAnonPw ){
183
- @ <p>If you do not have a user-id, enter "<b>anonymous</b>" with a
184
- @ password of "<b>%h(zAnonPw)</b>".</p>
195
+ if( zAnonPw && !anonFlag ){
196
+ @ <p>The password for user "anonymous" is "<b>%h(zAnonPw)</b>".</p>
197
+ @ <p>&nbsp;</p>
185198
}else{
186
- @ <p>A valid user-id and password is required. Anonymous access
187
- @ is not allowed on this installation.</p>
199
+ @ <p>&nbsp;</p><p>&nbsp;</p>
188200
}
189201
}
190202
if( g.zLogin ){
191203
@ <br clear="both"><hr>
192204
@ <p>To log off the system (and delete your login cookie)
@@ -381,11 +393,11 @@
381393
void login_anonymous_available(void){
382394
if( !g.okHistory &&
383395
db_exists("SELECT 1 FROM user"
384396
" WHERE login='anonymous'"
385397
" AND cap LIKE '%%h%%'") ){
386
- @ <p><b>Note:</b> Many hyperlinks are omitted from this page to discourage
387
- @ <a href="http://en.wikipedia.org/wiki/Web_crawler">spiders</a>.
388
- @ You will be able to access information more easily if you
389
- @ <a href="%s(g.zTop)/login">login</a> as user "anonymous".</p>
398
+ const char *zUrl = PD("REQUEST_URI", "index");
399
+ @ <p>Many <font color="red">hyperlinks are disabled.</font><br />
400
+ @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
401
+ @ to enable hyperlinks.</p>
390402
}
391403
}
392404
--- src/login.c
+++ src/login.c
@@ -74,17 +74,19 @@
74 ** Generate the login page
75 */
76 void login_page(void){
77 const char *zUsername, *zPasswd, *zGoto;
78 const char *zNew1, *zNew2;
79 const char *zAnonPw;
 
80 char *zErrMsg = "";
81
82 login_check_credentials();
83 zUsername = P("u");
84 zPasswd = P("p");
85 zGoto = PD("g","index");
 
86 if( P("out")!=0 ){
87 const char *zCookieName = login_cookie_name();
88 cgi_set_cookie(zCookieName, "", 0, -86400);
89 cgi_redirect(zGoto);
90 }
@@ -147,21 +149,35 @@
147 }
148 style_header("Login/Logout");
149 @ %s(zErrMsg)
150 @ <form action="login" method="POST">
151 if( P("g") ){
152 @ <input type="hidden" name="nxp" value="%h(P("g"))">
153 }
154 @ <table align="left" hspace="10">
155 @ <tr>
156 @ <td align="right">User ID:</td>
157 @ <td><input type="text" name="u" value="" size=30></td>
 
 
 
 
158 @ </tr>
159 @ <tr>
160 @ <td align="right">Password:</td>
161 @ <td><input type="password" name="p" value="" size=30></td>
162 @ </tr>
 
 
 
 
 
 
 
 
 
 
163 @ <tr>
164 @ <td></td>
165 @ <td><input type="submit" name="in" value="Login"></td>
166 @ </tr>
167 @ </table>
@@ -174,19 +190,15 @@
174 @ enter the user-id and password at the left and press the
175 @ "Login" button. Your user name will be stored in a browser cookie.
176 @ You must configure your web browser to accept cookies in order for
177 @ the login to take.</p>
178 if( g.zLogin==0 ){
179 zAnonPw = db_text(0, "SELECT pw FROM user"
180 " WHERE login='anonymous'"
181 " AND cap!=''");
182 if( zAnonPw ){
183 @ <p>If you do not have a user-id, enter "<b>anonymous</b>" with a
184 @ password of "<b>%h(zAnonPw)</b>".</p>
185 }else{
186 @ <p>A valid user-id and password is required. Anonymous access
187 @ is not allowed on this installation.</p>
188 }
189 }
190 if( g.zLogin ){
191 @ <br clear="both"><hr>
192 @ <p>To log off the system (and delete your login cookie)
@@ -381,11 +393,11 @@
381 void login_anonymous_available(void){
382 if( !g.okHistory &&
383 db_exists("SELECT 1 FROM user"
384 " WHERE login='anonymous'"
385 " AND cap LIKE '%%h%%'") ){
386 @ <p><b>Note:</b> Many hyperlinks are omitted from this page to discourage
387 @ <a href="http://en.wikipedia.org/wiki/Web_crawler">spiders</a>.
388 @ You will be able to access information more easily if you
389 @ <a href="%s(g.zTop)/login">login</a> as user "anonymous".</p>
390 }
391 }
392
--- src/login.c
+++ src/login.c
@@ -74,17 +74,19 @@
74 ** Generate the login page
75 */
76 void login_page(void){
77 const char *zUsername, *zPasswd, *zGoto;
78 const char *zNew1, *zNew2;
79 const char *zAnonPw = 0;
80 int anonFlag;
81 char *zErrMsg = "";
82
83 login_check_credentials();
84 zUsername = P("u");
85 zPasswd = P("p");
86 zGoto = PD("g","index");
87 anonFlag = P("anon")!=0;
88 if( P("out")!=0 ){
89 const char *zCookieName = login_cookie_name();
90 cgi_set_cookie(zCookieName, "", 0, -86400);
91 cgi_redirect(zGoto);
92 }
@@ -147,21 +149,35 @@
149 }
150 style_header("Login/Logout");
151 @ %s(zErrMsg)
152 @ <form action="login" method="POST">
153 if( P("g") ){
154 @ <input type="hidden" name="g" value="%h(P("g"))">
155 }
156 @ <table align="left" hspace="10">
157 @ <tr>
158 @ <td align="right">User ID:</td>
159 if( anonFlag ){
160 @ <td><input type="text" name="u" value="anonymous" size=30></td>
161 }else{
162 @ <td><input type="text" name="u" value="" size=30></td>
163 }
164 @ </tr>
165 @ <tr>
166 @ <td align="right">Password:</td>
167 @ <td><input type="password" name="p" value="" size=30></td>
168 @ </tr>
169 if( g.zLogin==0 ){
170 zAnonPw = db_text(0, "SELECT pw FROM user"
171 " WHERE login='anonymous'"
172 " AND cap!=''");
173 if( zAnonPw && anonFlag ){
174 @ <tr><td></td>
175 @ <td>The anonymous password is "<b>%h(zAnonPw)</b>".</td>
176 @ </tr>
177 }
178 }
179 @ <tr>
180 @ <td></td>
181 @ <td><input type="submit" name="in" value="Login"></td>
182 @ </tr>
183 @ </table>
@@ -174,19 +190,15 @@
190 @ enter the user-id and password at the left and press the
191 @ "Login" button. Your user name will be stored in a browser cookie.
192 @ You must configure your web browser to accept cookies in order for
193 @ the login to take.</p>
194 if( g.zLogin==0 ){
195 if( zAnonPw && !anonFlag ){
196 @ <p>The password for user "anonymous" is "<b>%h(zAnonPw)</b>".</p>
197 @ <p>&nbsp;</p>
 
 
 
198 }else{
199 @ <p>&nbsp;</p><p>&nbsp;</p>
 
200 }
201 }
202 if( g.zLogin ){
203 @ <br clear="both"><hr>
204 @ <p>To log off the system (and delete your login cookie)
@@ -381,11 +393,11 @@
393 void login_anonymous_available(void){
394 if( !g.okHistory &&
395 db_exists("SELECT 1 FROM user"
396 " WHERE login='anonymous'"
397 " AND cap LIKE '%%h%%'") ){
398 const char *zUrl = PD("REQUEST_URI", "index");
399 @ <p>Many <font color="red">hyperlinks are disabled.</font><br />
400 @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
401 @ to enable hyperlinks.</p>
402 }
403 }
404
--- src/tagview.c
+++ src/tagview.c
@@ -144,10 +144,11 @@
144144
login_check_credentials();
145145
if( !g.okRdWiki ){
146146
login_needed();
147147
}
148148
style_header("Tags");
149
+ login_anonymous_available();
149150
tagview_page_search_miniform();
150151
@ <hr/>
151152
char const * check = 0;
152153
if( 0 != (check = P("tagid")) ){
153154
tagview_page_tag_by_id( atoi(check) );
154155
--- src/tagview.c
+++ src/tagview.c
@@ -144,10 +144,11 @@
144 login_check_credentials();
145 if( !g.okRdWiki ){
146 login_needed();
147 }
148 style_header("Tags");
 
149 tagview_page_search_miniform();
150 @ <hr/>
151 char const * check = 0;
152 if( 0 != (check = P("tagid")) ){
153 tagview_page_tag_by_id( atoi(check) );
154
--- src/tagview.c
+++ src/tagview.c
@@ -144,10 +144,11 @@
144 login_check_credentials();
145 if( !g.okRdWiki ){
146 login_needed();
147 }
148 style_header("Tags");
149 login_anonymous_available();
150 tagview_page_search_miniform();
151 @ <hr/>
152 char const * check = 0;
153 if( 0 != (check = P("tagid")) ){
154 tagview_page_tag_by_id( atoi(check) );
155
+26 -4
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -785,10 +785,28 @@
785785
int n = strlen(z);
786786
if( n<4 || n>UUID_SIZE ) return 0;
787787
if( !validate16(z, n) ) return 0;
788788
return 1;
789789
}
790
+
791
+/*
792
+** Return true if the given hyperlink should be implemented for
793
+** the current login.
794
+*/
795
+static int okToHyperlink(const char *zTarget){
796
+ if( g.okHistory ) return 1;
797
+ if( strncmp(zTarget, "http:", 5)==0
798
+ || strncmp(zTarget, "https:", 6)==0
799
+ || strncmp(zTarget, "ftp:", 4)==0
800
+ || strncmp(zTarget, "mailto:", 7)==0
801
+ ){
802
+ return 1;
803
+ }
804
+ if( zTarget[0]=='/' || is_valid_uuid(zTarget) ) return 0;
805
+ if( wiki_name_is_wellformed(zTarget) ) return 1;
806
+ return 0;
807
+}
790808
791809
/*
792810
** Resolve a hyperlink. The argument is the content of the [...]
793811
** in the wiki. Append the URL to the output of the Renderer.
794812
*/
@@ -930,10 +948,11 @@
930948
case TOKEN_LINK: {
931949
char *zTarget;
932950
char *zDisplay = 0;
933951
int i, j;
934952
int savedState;
953
+ int ok;
935954
startAutoParagraph(p);
936955
zTarget = &z[1];
937956
for(i=1; z[i] && z[i]!=']'; i++){
938957
if( z[i]=='|' && zDisplay==0 ){
939958
zDisplay = &z[i+1];
@@ -945,19 +964,22 @@
945964
if( zDisplay==0 ){
946965
zDisplay = zTarget;
947966
}else{
948967
while( isspace(*zDisplay) ) zDisplay++;
949968
}
950
- blob_append(p->pOut, "<a href=\"", -1);
951
- resolveHyperlink(zTarget, p);
952
- blob_append(p->pOut, "\">", -1);
969
+ ok = okToHyperlink(zTarget);
970
+ if( ok ){
971
+ blob_append(p->pOut, "<a href=\"", -1);
972
+ resolveHyperlink(zTarget, p);
973
+ blob_append(p->pOut, "\">", -1);
974
+ }
953975
savedState = p->state;
954976
p->state &= ~ALLOW_WIKI;
955977
p->state |= FONT_MARKUP_ONLY;
956978
wiki_render(p, zDisplay);
957979
p->state = savedState;
958
- blob_append(p->pOut, "</a>", 4);
980
+ if( ok ) blob_append(p->pOut, "</a>", 4);
959981
break;
960982
}
961983
case TOKEN_TEXT: {
962984
startAutoParagraph(p);
963985
blob_append(p->pOut, z, n);
964986
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -785,10 +785,28 @@
785 int n = strlen(z);
786 if( n<4 || n>UUID_SIZE ) return 0;
787 if( !validate16(z, n) ) return 0;
788 return 1;
789 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790
791 /*
792 ** Resolve a hyperlink. The argument is the content of the [...]
793 ** in the wiki. Append the URL to the output of the Renderer.
794 */
@@ -930,10 +948,11 @@
930 case TOKEN_LINK: {
931 char *zTarget;
932 char *zDisplay = 0;
933 int i, j;
934 int savedState;
 
935 startAutoParagraph(p);
936 zTarget = &z[1];
937 for(i=1; z[i] && z[i]!=']'; i++){
938 if( z[i]=='|' && zDisplay==0 ){
939 zDisplay = &z[i+1];
@@ -945,19 +964,22 @@
945 if( zDisplay==0 ){
946 zDisplay = zTarget;
947 }else{
948 while( isspace(*zDisplay) ) zDisplay++;
949 }
950 blob_append(p->pOut, "<a href=\"", -1);
951 resolveHyperlink(zTarget, p);
952 blob_append(p->pOut, "\">", -1);
 
 
 
953 savedState = p->state;
954 p->state &= ~ALLOW_WIKI;
955 p->state |= FONT_MARKUP_ONLY;
956 wiki_render(p, zDisplay);
957 p->state = savedState;
958 blob_append(p->pOut, "</a>", 4);
959 break;
960 }
961 case TOKEN_TEXT: {
962 startAutoParagraph(p);
963 blob_append(p->pOut, z, n);
964
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -785,10 +785,28 @@
785 int n = strlen(z);
786 if( n<4 || n>UUID_SIZE ) return 0;
787 if( !validate16(z, n) ) return 0;
788 return 1;
789 }
790
791 /*
792 ** Return true if the given hyperlink should be implemented for
793 ** the current login.
794 */
795 static int okToHyperlink(const char *zTarget){
796 if( g.okHistory ) return 1;
797 if( strncmp(zTarget, "http:", 5)==0
798 || strncmp(zTarget, "https:", 6)==0
799 || strncmp(zTarget, "ftp:", 4)==0
800 || strncmp(zTarget, "mailto:", 7)==0
801 ){
802 return 1;
803 }
804 if( zTarget[0]=='/' || is_valid_uuid(zTarget) ) return 0;
805 if( wiki_name_is_wellformed(zTarget) ) return 1;
806 return 0;
807 }
808
809 /*
810 ** Resolve a hyperlink. The argument is the content of the [...]
811 ** in the wiki. Append the URL to the output of the Renderer.
812 */
@@ -930,10 +948,11 @@
948 case TOKEN_LINK: {
949 char *zTarget;
950 char *zDisplay = 0;
951 int i, j;
952 int savedState;
953 int ok;
954 startAutoParagraph(p);
955 zTarget = &z[1];
956 for(i=1; z[i] && z[i]!=']'; i++){
957 if( z[i]=='|' && zDisplay==0 ){
958 zDisplay = &z[i+1];
@@ -945,19 +964,22 @@
964 if( zDisplay==0 ){
965 zDisplay = zTarget;
966 }else{
967 while( isspace(*zDisplay) ) zDisplay++;
968 }
969 ok = okToHyperlink(zTarget);
970 if( ok ){
971 blob_append(p->pOut, "<a href=\"", -1);
972 resolveHyperlink(zTarget, p);
973 blob_append(p->pOut, "\">", -1);
974 }
975 savedState = p->state;
976 p->state &= ~ALLOW_WIKI;
977 p->state |= FONT_MARKUP_ONLY;
978 wiki_render(p, zDisplay);
979 p->state = savedState;
980 if( ok ) blob_append(p->pOut, "</a>", 4);
981 break;
982 }
983 case TOKEN_TEXT: {
984 startAutoParagraph(p);
985 blob_append(p->pOut, z, n);
986

Keyboard Shortcuts

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