tutor.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /** --- BEGIN COPYRIGHT BLOCK ---
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. --- END COPYRIGHT BLOCK --- */
  38. /*
  39. * tutor.c - Take a qs, and spit out the appropriate tutorial
  40. *
  41. * All blame to Mike McCool
  42. */
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include "dsgw.h"
  46. #define BASE_MAN_DIRECTORY "manual/"
  47. #define BASE_INFO_DIRECTORY "info/"
  48. #define HELP_INDEX_HTML "manual/index.html"
  49. /*#define MANUAL_HPATH "bin/lang?file=" DSGW_MANUALSHORTCUT "/"*/
  50. /* Copied from ldapserver/lib/base/util.c */
  51. static int
  52. my_util_uri_is_evil(char *t)
  53. {
  54. register int x;
  55. for(x = 0; t[x]; ++x) {
  56. if(t[x] == '/') {
  57. if(t[x+1] == '/')
  58. return 1;
  59. if(t[x+1] == '.') {
  60. switch(t[x+2]) {
  61. case '.':
  62. if((!t[x+3]) || (t[x+3] == '/'))
  63. return 1;
  64. case '/':
  65. case '\0':
  66. return 1;
  67. }
  68. }
  69. }
  70. #ifdef XP_WIN32
  71. /* On NT, the directory "abc...." is the same as "abc"
  72. * The only cheap way to catch this globally is to disallow
  73. * names with the trailing "."s. Hopefully this is not over
  74. * restrictive
  75. */
  76. if ((t[x] == '.') && ( (t[x+1] == '/') || (t[x+1] == '\0') )) {
  77. return 1;
  78. }
  79. #endif
  80. }
  81. return 0;
  82. }
  83. FILE *
  84. _open_html_file( char *filename )
  85. {
  86. FILE *f;
  87. char *mypath;
  88. char *p;
  89. p = dsgw_file2path( DSGW_MANROOT, "slapd/gw/" );
  90. mypath = (char *)dsgw_ch_malloc( strlen( p ) +
  91. strlen( filename ) + 1 );
  92. sprintf( mypath, "%s%s", p, filename );
  93. if (!(f = fopen( mypath, "r" ))) {
  94. dsgw_error( DSGW_ERR_OPENHTMLFILE, filename, DSGW_ERROPT_EXIT,
  95. 0, NULL );
  96. }
  97. free( p );
  98. free( mypath );
  99. return f;
  100. }
  101. /* Had to copy and paste so wouldn't set referer. */
  102. void _my_return_html_file(char *filename, char *base) {
  103. char line[BIG_LINE];
  104. FILE *html = _open_html_file(filename);
  105. if(base) {
  106. char *tmp;
  107. char *surl=getenv("SERVER_URL");
  108. char *sn=dsgw_ch_strdup(getenv("SCRIPT_NAME"));
  109. tmp=strchr(&(sn[1]), '/');
  110. *tmp='\0';
  111. dsgw_emitf("<BASE href=\"%s%s/%s\">\n", surl, sn, base);
  112. }
  113. while( fgets(line, BIG_LINE, html)) {
  114. dsgw_emits( line );
  115. }
  116. }
  117. int
  118. main(
  119. int argc,
  120. char *argv[]
  121. #ifdef DSGW_DEBUG
  122. ,char *env[]
  123. #endif
  124. )
  125. {
  126. char *qs = getenv("QUERY_STRING");
  127. char *html=NULL;
  128. char *base=NULL;
  129. #ifdef DSGW_DEBUG
  130. dsgw_logstringarray( "env", env );
  131. #endif
  132. if(qs == NULL || *qs == '\0') {
  133. dsgw_send_header();
  134. _my_return_html_file(BASE_MAN_DIRECTORY HELP_INDEX_HTML, NULL);
  135. exit(0);
  136. } else {
  137. /* parse the query string: */
  138. auto char *p, *iter = NULL;
  139. /*get a pointer to the context. It should be the last part of the qs*/
  140. p = ldap_utf8strtok_r( qs, "&", &iter );
  141. /*
  142. * Get the conf file name. It'll be translated
  143. * into /dsgw/context/CONTEXT.conf if
  144. * CONTEXT is all alphanumeric (no slahes,
  145. * or dots). CONTEXT is passed into the cgi.
  146. * if context=CONTEXT is not there, or PATH_INFO
  147. * was used, then use dsgw.conf
  148. */
  149. if ( iter != NULL && !strncasecmp( iter, "context=", 8 )) {
  150. context = dsgw_ch_strdup( iter + 8 );
  151. dsgw_form_unescape( context );
  152. }
  153. }
  154. dsgw_init( argc, argv, DSGW_METHOD_GET );
  155. html = (char *) dsgw_ch_malloc(strlen(qs)+10+10);
  156. sprintf(html, "%s.html", qs);
  157. if (my_util_uri_is_evil(html)) {
  158. dsgw_send_header();
  159. dsgw_emits( "<CENTER><H2>Error</H2></CENTER>\n"
  160. "<P>\n"
  161. "URL contains dangerous characters. Cannot display\n"
  162. "help text." );
  163. exit( 0 );
  164. }
  165. if(qs[0]=='!') {
  166. qs++;
  167. if(!strncmp(qs, BASE_INFO_DIRECTORY, strlen(BASE_INFO_DIRECTORY))) {
  168. sprintf(html, "%s.html", qs);
  169. } else if(!strncmp(qs, BASE_MAN_DIRECTORY, strlen(BASE_MAN_DIRECTORY))) {
  170. if(!strstr(qs, ".html")) {
  171. sprintf(html, "%s.htm", qs);
  172. } else {
  173. sprintf(html, "%s", qs);
  174. }
  175. base=qs;
  176. }
  177. else {
  178. char line[BIG_LINE];
  179. FILE *map=NULL;
  180. char *man_index=NULL;
  181. man_index = dsgw_file2path ( DSGW_MANROOT, "slapd/gw/manual/index.map" );
  182. html[0]='\0';
  183. map=fopen(man_index, "r");
  184. if(!map)
  185. goto ohwell;
  186. while(fgets(line, BIG_LINE, map)) {
  187. if(line[0]==';')
  188. continue;
  189. else if(ldap_utf8isspace(line))
  190. continue;
  191. else {
  192. /* parse out the line */
  193. register char *head=NULL, *tail=NULL;
  194. int found;
  195. head=&(line[0]);
  196. tail=head;
  197. found=0;
  198. while(*tail) {
  199. if(ldap_utf8isspace(tail) || *tail=='=') {
  200. *tail='\0';
  201. found=1;
  202. /* get rid of extra stuff at the end */
  203. tail++;
  204. while(1) {
  205. if (*tail == 0) {
  206. ++tail; /* This looks wrong. */
  207. break;
  208. }
  209. LDAP_UTF8INC(tail);
  210. if((!ldap_utf8isspace(tail)) && (*tail!='='))
  211. break;
  212. }
  213. break;
  214. }
  215. LDAP_UTF8INC(tail);
  216. }
  217. if(!found) continue;
  218. /* script name is in head */
  219. if(strncasecmp(head, qs, strlen(qs))) {
  220. continue;
  221. }
  222. /* match found. get the actual file name */
  223. head=tail;
  224. /* Step on CRs and LFs. */
  225. while(*tail) {
  226. if((*tail=='\r') || (*tail=='\n') || (*tail==';')) {
  227. *tail='\0';
  228. break;
  229. }
  230. LDAP_UTF8INC(tail);
  231. }
  232. #if 0
  233. /* No longer remove whitespace at end of line. Now is whitespace in link. */
  234. while(*LDAP_UTF8DEC(tail)) {
  235. if(ldap_utf8isspace(tail)) *tail='\0';
  236. else break;
  237. }
  238. #endif
  239. /* assumedly, head should now have the proper HTML file
  240. * from the manual inside. redirect the client 'cause
  241. * there's no other way to get them to jump to the
  242. * right place.
  243. * Looks like:
  244. * http://host:port/dsgw/bin/lang?context=CONTEXT&file=.MANUAL/FILE.HTM
  245. * Where MANUAL is literal
  246. */
  247. dsgw_emitf("Location: %s%s/%s\n\n",
  248. gc->gc_urlpfxmain, DSGW_MANUALSHORTCUT, head);
  249. fclose(map);
  250. exit(0);
  251. }
  252. }
  253. fclose(map);
  254. free( man_index );
  255. ohwell:
  256. if(!html[0])
  257. sprintf(html, "%s%s.html", BASE_MAN_DIRECTORY, qs);
  258. }
  259. dsgw_send_header();
  260. _my_return_html_file(html, base);
  261. } else {
  262. dsgw_send_header();
  263. dsgw_emits("<TITLE>Directory Server Gateway Help</TITLE>\n");
  264. dsgw_emits("\n");
  265. dsgw_emits("<frameset BORDER=0 FRAMEBORDER=NO rows=\"57,*\" "
  266. "onLoad=\"top.master=top.opener.top;top.master.helpwin=self;\" "
  267. "onUnload=\"if (top.master) { top.master.helpwin=0; }\">\n" );
  268. dsgw_emitf("<frame src=\"%s?!info/infonav&context=%s\" scrolling=no "
  269. "marginwidth=0 marginheight=0 "
  270. "name=\"infobuttons\">\n", dsgw_getvp(DSGW_CGINUM_TUTOR), context);
  271. dsgw_emitf("<frame src=\"%s?!%s&context=%s\" "
  272. "name=\"infotopic\">\n", dsgw_getvp(DSGW_CGINUM_TUTOR), qs, context);
  273. dsgw_emits("</frameset>\n");
  274. }
  275. return 1;
  276. }