/* * Copyright 1995, 1998 Perforce Software. * * This file is part of WebKeeper, a perforce client apache module. * * License is hereby granted to use this software and distribute it * freely, as long as this copyright notice is retained and modifications * are clearly marked. * * ALL WARRANTIES ARE HEREBY DISCLAIMED. * * $Id: //public/perforce/webkeeper/mod_webkeep2.cc#3 $ */ /* * mod_webkeep2.cc -- C++ glue between webkeeper and Perforce Client API * * ClientUserWK sits upon the Perforce ClientApi, and webKeepPrint() * makes use of ClientUserWK. The web server Apache module mod_webkeep.c * interfaces to webKeepPrint() through webkeep.h. */ # include <clientapi.h> extern "C" { # include "mod_webkeep.h" } class ClientUserWK : public ClientUser { public: void OutputInfo( char level, char *data ) { if( sync ) return; (*printer->data)( printer, data); } void OutputError( char *errBuf ) { (*printer->error)( printer, errBuf , __WK_BAD_REQUEST); } void OutputText( char *data, int length ) { (*printer->text)( printer, data, length ); } void OutputBinary( char *data, int length ) { (*printer->text)( printer, data, length ); } WebKeepPrinter *printer; int sync; ClientUserWK () : ClientUser() { sync = 0; printer = NULL; } } ; /* begin cpatil */ /* First check if it is a file */ static int RW_TryPrint(ClientApi *client, char *path, WebKeepPrinter *printer) { if (printer->isDir == 1) { debugS("RW_TryPrint : %s is known to be a dir. Returning\n",path, "",""); return 0; } printer->ignoreerrors = 1; printer->print = 0; printer->collectinfo = 0; printer->errorcount = 0; // is it a file? if (printer->isFile == -1) { client->SetArgv(1, &path); client->Run("files"); if (printer->errorcount == 0) { // yes, it's a file printer->isFile = 1; printer->isDir = 0; } else { printer->isFile = 0; } } if (printer->isFile == 1) { printer->ignoreerrors = 0; printer->print = 1; client->SetArgv(1, &path); client->Run("print"); debugS("RW_TryPrint : p4 files %s found a file. Printing it. Printer status: %d\n", path, printer->status ,""); return 1; } else { debugS("RW_TryPrint : p4 files %s not a file. Returning\n",path, "",""); return 0; } } /* THen check if it is a dir */ static int RW_TryList(ClientApi *client, char *path, WebKeepPrinter *printer) { printer->ignoreerrors = 1; printer->print = 0; printer->collectinfo = 0; printer->errorcount = 0; // is it a dir? if (printer->isDir == -1) { client->SetArgv(1, &path); client->Run("dirs"); if (printer->errorcount == 0) { // yes, it's a dir printer->isDir = 1; printer->isFile = 0; } else { debugS("RW_TryList : p4 dirs %s returned error. Returing\n",path, "", ""); printer->isDir = 0; return 0; } } if(printer->isDir == 1) { // Create a globpath to get the full listing of the directories char *globpath = new char[::strlen(path) + 3]; ::strcpy(globpath, path); ::strcat(globpath, "/*"); printer->collectinfo = 1; client->SetArgv(1, &globpath); debugS("RW_TryList : Running p4 dirs %s on globpath\n",globpath, "", ""); client->Run("dirs"); client->SetArgv(1, &globpath); debugS("RW_TryList : Running p4 files %s on globpath\n",globpath, "", ""); client->Run("files"); (*(printer->dir))(printer); delete[] globpath; return 1; } else { debugS("RW_TryList : Path %s Not a dir. Returning\n",path, "", ""); return 0; } } /* End cpatil */ extern "C" void webKeepPrint( WebKeepConnect *p4, char *path, WebKeepPrinter *printer ) { Error e[1]; ClientUserWK ui; ClientApi client( &ui ); int status = 1; // Plug in API extentions: user's closure parameter and // dispatch table. ui.printer = printer; if( p4->port ) client.SetPort( p4->port ); if( p4->user ) client.SetUser( p4->user ); if( p4->pass ) client.SetPassword( p4->pass ); if( p4->client ) client.SetClient( p4->client ); if( p4->sync ) ui.sync = 1; // Connect. client.Init( e ); if( !e->Test() ) { /* begin cpatil */ char *pathcopy = new char[::strlen(path) + 1]; ::strcpy(pathcopy, path); if (pathcopy[::strlen(pathcopy) - 1] == '/') { pathcopy[::strlen(pathcopy) - 1] = 0; } debugS("WebKeepPrint : Using path %s and pathcopy %s\n",path, pathcopy, ""); status = (RW_TryPrint(&client, pathcopy, printer) || RW_TryList(&client, pathcopy, printer)); delete[] pathcopy; debugS("WebKeepPrint : TryPrint / TryList returned with status %d. printer status: %d\n", status, printer->status, ""); if (status == 0) { (*printer->error)(printer, "Not found!", __WK_NOT_FOUND); } } client.Final( e ); if( e->Test() ) { StrBuf buf; e->Fmt( &buf ); debug("WebKeepPrint : Some error with p4 client. Returning SERVER_ERROR"); (*printer->error)( printer, buf.Text() , __WK_SERVER_ERROR); } debugS("WebKeepPrint : Final status %d\n", printer->status, "", ""); } extern "C" void webKeepSync( WebKeepConnect *p4, char *path, WebKeepPrinter *printer ) { Error e[1]; ClientUserWK ui; ClientApi client( &ui ); ui.printer = printer; if( p4->port ) client.SetPort( p4->port ); if( p4->user ) client.SetUser( p4->user ); if( p4->pass ) client.SetPassword( p4->pass ); if( p4->client ) client.SetClient( p4->client ); if( p4->sync ) ui.sync = 1; // Connect. client.Init( e ); if( !e->Test() ) { client.SetArgv( 1, &path ); client.Run( "sync" ); client.Final( e ); } if( e->Test() ) { StrBuf buf; e->Fmt( &buf ); (*printer->error)( printer, buf.Text() , __WK_SERVER_ERROR); } debugS("WebKeepSync : Final status %d\n", printer->status, "", ""); } class ClientUserFileExists : public ClientUser { public: ClientUserFileExists() { fexists = 0; } void OutputInfo( char, char * ) { fexists = 1; } void OutputError( char * ) { fexists = 0; } void OutputText( char *, int ) {} void OutputBinary( char *, int ) {} int FileExists() { return fexists; } private: int fexists; }; extern "C" int webKeepFileExists( WebKeepConnect *p4, char *path ) { Error e[1]; ClientUserFileExists ui; ClientApi client( &ui ); if( p4->port ) client.SetPort( p4->port ); if( p4->user ) client.SetUser( p4->user ); if( p4->pass ) client.SetPassword( p4->pass ); if( p4->client ) client.SetClient( p4->client ); client.Init( e ); if( !e->Test() ) { client.SetArgv( 1, &path ); client.Run( "files" ); client.Final( e ); } return ui.FileExists(); } extern "C" int webKeepDirExists( WebKeepConnect *p4, char *path ) { Error e[1]; ClientUserFileExists ui; ClientApi client( &ui ); if( p4->port ) client.SetPort( p4->port ); if( p4->user ) client.SetUser( p4->user ); if( p4->pass ) client.SetPassword( p4->pass ); if( p4->client ) client.SetClient( p4->client ); client.Init( e ); if( !e->Test() ) { int length = strlen( path ); int endsInSlash = ( path[length - 1] == '/' ); /* * Since we don't have access to the Apache pool here, we will * just blank the slash out and restore it when we're done. */ if( endsInSlash ) { path[length - 1] = '\0'; } client.SetArgv( 1, &path ); client.Run( "dirs" ); client.Final( e ); if( endsInSlash ) { path[length - 1] = '/'; } } return ui.FileExists(); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 1844 | Chetan Patil |
Made following changes to the webkeeper code: - Directory listing (uses p4 dirs and files to build the listing) - If for a directory, the trailing slash is missing, redirect to a new url with a trailing slash (mod_dir code). - Debug statements for debugging - Bug fix where sync was being used unintialized (mod_webkeep2.cc). This has not been tested with the syncing capability of Webkeeper. - Code outputs http content type based on if the data is gif, jpeg or binary data; previously it only output octet-stream for all non-textual data. - Code tries to reduce the impact on the perforce server by caching some information between processing phases (isFile and isDir) - Misc Minor edits |