/** * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to * license terms. Copyright © 2001 Sun Microsystems, Inc. * Some preexisting portions Copyright © 2001 Netscape Communications Corp. * All rights reserved. */ /* * tutor.c - Take a qs, and spit out the appropriate tutorial * * All blame to Mike McCool */ #include #include #include "dsgw.h" #define BASE_MAN_DIRECTORY "manual/" #define BASE_INFO_DIRECTORY "info/" #define HELP_INDEX_HTML "manual/index.html" /*#define MANUAL_HPATH "bin/lang?file=" DSGW_MANUALSHORTCUT "/"*/ /* Copied from ldapserver/lib/base/util.c */ static int my_util_uri_is_evil(char *t) { register int x; for(x = 0; t[x]; ++x) { if(t[x] == '/') { if(t[x+1] == '/') return 1; if(t[x+1] == '.') { switch(t[x+2]) { case '.': if((!t[x+3]) || (t[x+3] == '/')) return 1; case '/': case '\0': return 1; } } } #ifdef XP_WIN32 /* On NT, the directory "abc...." is the same as "abc" * The only cheap way to catch this globally is to disallow * names with the trailing "."s. Hopefully this is not over * restrictive */ if ((t[x] == '.') && ( (t[x+1] == '/') || (t[x+1] == '\0') )) { return 1; } #endif } return 0; } FILE * _open_html_file( char *filename ) { FILE *f; char *mypath; char *p; p = dsgw_file2path( DSGW_MANROOT, "slapd/gw/" ); mypath = (char *)dsgw_ch_malloc( strlen( p ) + strlen( filename ) + 1 ); sprintf( mypath, "%s%s", p, filename ); if (!(f = fopen( mypath, "r" ))) { dsgw_error( DSGW_ERR_OPENHTMLFILE, filename, DSGW_ERROPT_EXIT, 0, NULL ); } free( p ); free( mypath ); return f; } /* Had to copy and paste so wouldn't set referer. */ void _my_return_html_file(char *filename, char *base) { char line[BIG_LINE]; FILE *html = _open_html_file(filename); if(base) { char *tmp; char *surl=getenv("SERVER_URL"); char *sn=dsgw_ch_strdup(getenv("SCRIPT_NAME")); tmp=strchr(&(sn[1]), '/'); *tmp='\0'; dsgw_emitf("\n", surl, sn, base); } while( fgets(line, BIG_LINE, html)) { dsgw_emits( line ); } } int main( int argc, char *argv[] #ifdef DSGW_DEBUG ,char *env[] #endif ) { char *qs = getenv("QUERY_STRING"); char *html=NULL; char *base=NULL; #ifdef DSGW_DEBUG dsgw_logstringarray( "env", env ); #endif if(qs == NULL || *qs == '\0') { dsgw_send_header(); _my_return_html_file(BASE_MAN_DIRECTORY HELP_INDEX_HTML, NULL); exit(0); } else { /* parse the query string: */ auto char *p, *iter = NULL; /*get a pointer to the context. It should be the last part of the qs*/ p = ldap_utf8strtok_r( qs, "&", &iter ); /* * Get the conf file name. It'll be translated * into /dsgw/context/CONTEXT.conf if * CONTEXT is all alphanumeric (no slahes, * or dots). CONTEXT is passed into the cgi. * if context=CONTEXT is not there, or PATH_INFO * was used, then use dsgw.conf */ if ( iter != NULL && !strncasecmp( iter, "context=", 8 )) { context = dsgw_ch_strdup( iter + 8 ); dsgw_form_unescape( context ); } } dsgw_init( argc, argv, DSGW_METHOD_GET ); html = (char *) dsgw_ch_malloc(strlen(qs)+10+10); sprintf(html, "%s.html", qs); if (my_util_uri_is_evil(html)) { dsgw_send_header(); dsgw_emits( "

Error

\n" "

\n" "URL contains dangerous characters. Cannot display\n" "help text." ); exit( 0 ); } if(qs[0]=='!') { qs++; if(!strncmp(qs, BASE_INFO_DIRECTORY, strlen(BASE_INFO_DIRECTORY))) { sprintf(html, "%s.html", qs); } else if(!strncmp(qs, BASE_MAN_DIRECTORY, strlen(BASE_MAN_DIRECTORY))) { if(!strstr(qs, ".html")) { sprintf(html, "%s.htm", qs); } else { sprintf(html, "%s", qs); } base=qs; } else { char line[BIG_LINE]; FILE *map=NULL; char *man_index=NULL; man_index = dsgw_file2path ( DSGW_MANROOT, "slapd/gw/manual/index.map" ); html[0]='\0'; map=fopen(man_index, "r"); if(!map) goto ohwell; while(fgets(line, BIG_LINE, map)) { if(line[0]==';') continue; else if(ldap_utf8isspace(line)) continue; else { /* parse out the line */ register char *head=NULL, *tail=NULL; int found; head=&(line[0]); tail=head; found=0; while(*tail) { if(ldap_utf8isspace(tail) || *tail=='=') { *tail='\0'; found=1; /* get rid of extra stuff at the end */ tail++; while(1) { if (*tail == 0) { ++tail; /* This looks wrong. */ break; } LDAP_UTF8INC(tail); if((!ldap_utf8isspace(tail)) && (*tail!='=')) break; } break; } LDAP_UTF8INC(tail); } if(!found) continue; /* script name is in head */ if(strncasecmp(head, qs, strlen(qs))) { continue; } /* match found. get the actual file name */ head=tail; /* Step on CRs and LFs. */ while(*tail) { if((*tail=='\r') || (*tail=='\n') || (*tail==';')) { *tail='\0'; break; } LDAP_UTF8INC(tail); } #if 0 /* No longer remove whitespace at end of line. Now is whitespace in link. */ while(*LDAP_UTF8DEC(tail)) { if(ldap_utf8isspace(tail)) *tail='\0'; else break; } #endif /* assumedly, head should now have the proper HTML file * from the manual inside. redirect the client 'cause * there's no other way to get them to jump to the * right place. * Looks like: * http://host:port/dsgw/bin/lang?context=CONTEXT&file=.MANUAL/FILE.HTM * Where MANUAL is literal */ dsgw_emitf("Location: %s%s/%s\n\n", gc->gc_urlpfxmain, DSGW_MANUALSHORTCUT, head); fclose(map); exit(0); } } fclose(map); free( man_index ); ohwell: if(!html[0]) sprintf(html, "%s%s.html", BASE_MAN_DIRECTORY, qs); } dsgw_send_header(); _my_return_html_file(html, base); } else { dsgw_send_header(); dsgw_emits("Directory Server Gateway Help\n"); dsgw_emits("\n"); dsgw_emits("\n" ); dsgw_emitf("\n", dsgw_getvp(DSGW_CGINUM_TUTOR), context); dsgw_emitf("\n", dsgw_getvp(DSGW_CGINUM_TUTOR), qs, context); dsgw_emits("\n"); } return 1; }