// // Copyright 2000 Perforce Software. All rights reserved. // // This file is part of Perforce - the FAST SCM System. // // p4wRelocate: // Send LOCATION directive to remap url to expected p4web syntax // ------------------------------------- // Includes // #include <stdlib.h> #include <string.h> #include <p4wp4.h> #include "p4wStrBuf.h" #include "p4wHtml.h" #include "p4wMenuPane.h" #include "p4wWorkspacePane.h" #include "p4wPasswdTestPane.h" #include "p4wClientRootPane.h" #include "p4wFilePane.h" #include "p4wLoginView.h" #include "p4wWherePane.h" #include "p4wRelocate.h" // ------------------------------------- // Constructors and destructor. // p4wRelocate::p4wRelocate(p4wRequest & Request, AllCommands cmd) : p4wView(Request), fRequest(Request), fCommand(cmd), fError(0), fNullPath(0), fPasswordSet(0), fCreateBtn(0), fClose(0), fLoadUrl(0) { // // Set flags in new base. // Spec spec; StrBufDict specTable; int workspaceCmd = 0; int passwdCmd = 0; const StrPtr *client = NULL; const StrPtr *newclient = NULL; const StrPtr *view = NULL; const StrPtr *oldPassword = NULL; const StrPtr *newPass1 = NULL; const StrPtr *newPass2 = NULL; StrBuf workPath; // // If this is a configuration request, we need to set // the base values here before the rest of the page // is drawn. if ( cmd == AC_CONFIGPROCESSOR ) { const StrPtr *port = NULL; const StrPtr *bitbOn = NULL; const StrPtr *bitbRev = NULL; const StrPtr *pageContent = NULL; const StrPtr *diffFlag = NULL; const StrPtr *diffOutFlag = NULL; const StrPtr *contextLines = NULL; const StrPtr *diffLiWrap = NULL; const StrPtr *resFlag = NULL; const StrPtr *thumbCols = NULL; const StrPtr *thumbSize = NULL; const StrPtr *thumbMag = NULL; const StrPtr *thumbBorder = NULL; const StrPtr *thumbNoCSS = NULL; const StrPtr *thumbWrap = NULL; const StrPtr *oldAnnotate = NULL; const StrPtr *pageCache = NULL; const StrPtr *fixesAlways = NULL; const StrPtr *showLineNo = NULL; const StrPtr *showP4Cmds = NULL; const StrPtr *showContentHist = NULL; const StrPtr *hideCols = NULL; const StrPtr *browseOnly = NULL; const StrPtr *eXperimental = NULL; const StrPtr *screenChunks = NULL; const StrPtr *forceDefaults = NULL; const StrPtr *save = NULL; const StrPtr *defaults = NULL; const StrPtr *restore = NULL; if( fRequest.ProcessForm( spec , &specTable ) ) { restore = specTable.GetVar( "restore" ); if (restore) { fRequest.ReplaceBase( "sr", NULL ); fRequest.ReplaceBase( "pt", NULL ); fRequest.ReplaceBase( "cl", fRequest.GetMultiUser() ? fRequest.GetClient().Text() : NULL ); fRequest.ReplaceBase( "dw", NULL ); fRequest.ReplaceBase( "dc", NULL ); fRequest.ReplaceBase( "dl", NULL ); fRequest.ReplaceBase( "rw", NULL ); fRequest.ReplaceBase( "thv", NULL ); fRequest.ReplaceBase( "thz", NULL ); fRequest.ReplaceBase( "mx", NULL ); fRequest.ReplaceBase( "md", "c" ); fRequest.ReplaceBase( "wr", NULL ); fRequest.ReplaceBase( "path", NULL ); fRequest.ReplaceBase( "pat", NULL ); fRequest.ReplaceBase( "is", NULL ); fRequest.ReplaceBase( "cf", NULL ); fRequest.ReplaceBase( "pb", NULL ); fRequest.ReplaceBase( "po", NULL ); fRequest.ReplaceBase( "df", NULL ); fRequest.ReplaceBase( "cdf", NULL ); fRequest.ReplaceBase( "rt", NULL ); defaults = restore; } else { port = specTable.GetVar( "Port" ); client = specTable.GetVar( "Client" ); bitbOn = specTable.GetVar( "bitbRadio" ); bitbRev = specTable.GetVar( "atVal" ); pageContent = specTable.GetVar( "contentLimit" ); diffFlag = specTable.GetVar( "diffFlag" ); diffOutFlag = specTable.GetVar( "diffOutFlag" ); contextLines = specTable.GetVar( "contextLines" ); diffLiWrap = specTable.GetVar( "diffLiWrap" ); resFlag = specTable.GetVar( "resFlag" ); thumbCols = specTable.GetVar( "thumbCols" ); thumbSize = specTable.GetVar( "thumbSize" ); thumbMag = specTable.GetVar( "thumbMag" ); thumbBorder = specTable.GetVar( "thumbBorder" ); thumbNoCSS = specTable.GetVar( "thumbNoCSS" ); thumbWrap = specTable.GetVar( "thumbWrap" ); oldAnnotate = specTable.GetVar( "oldAnnotate" ); pageCache = specTable.GetVar( "pageCache" ); fixesAlways = specTable.GetVar( "fixesAlways" ); showLineNo = specTable.GetVar( "showLineNo" ); showP4Cmds = specTable.GetVar( "showP4Cmds" ); showContentHist = specTable.GetVar( "showContentHist" ); hideCols = specTable.GetVar( "hideCols" ); browseOnly = specTable.GetVar( "browseOnly" ); eXperimental = specTable.GetVar( "eXperimental" ); screenChunks = specTable.GetVar( "screenChunks" ); forceDefaults = specTable.GetVar( "forceDefaults" ); oldPassword = specTable.GetVar( "OldPassword" ); newPass1 = specTable.GetVar( "NewPass1" ); newPass2 = specTable.GetVar( "NewPass2" ); save = specTable.GetVar( "save" ); defaults = specTable.GetVar( "defaults" ); } } if( forceDefaults && !defaults ) forceDefaults = NULL; if( bitbOn && *bitbOn == "on" ) { char *p = bitbRev->Text() + bitbRev->Length(); while (*--p == ' ') *p = '\0'; p = strchr(bitbRev->Text(), '<'); if (p) { char *q; StrBuf temp; temp.Set(p+1); for (q = temp.Text(); *q; q++) *q = tolower(*q); if (!strncmp(temp.Text(), "script", strlen("script"))) *p = '\0'; if (!strncmp(temp.Text(), "body", strlen("body"))) *p = '\0'; if (!strncmp(temp.Text(), "img", strlen("img"))) *p = '\0'; if (!strncmp(temp.Text(), "iframe", strlen("iframe"))) *p = '\0'; } if( *bitbRev->Text() == '@' ) fRequest.ReplaceBase( "sr", bitbRev->Text() + 1 ); else fRequest.ReplaceBase( "sr", bitbRev->Text() ); } if( bitbOn && *bitbOn == "off" ) fRequest.ReplaceBase( "sr", NULL ); if( fRequest.BypassAuth() && port && ( *port != fRequest.GetPort() ) ) fRequest.ReplaceBase( "pt", port->Text() ); if( client && ( *client != fRequest.GetClient() || fRequest.GetMultiUser() ) ) { char *p = strchr(client->Text(), '<'); if (p) { char *q; StrBuf temp; temp.Set(p+1); for (q = temp.Text(); *q; q++) *q = tolower(*q); if (!strncmp(temp.Text(), "script", strlen("script"))) *p = '\0'; if (!strncmp(temp.Text(), "body", strlen("body"))) *p = '\0'; if (!strncmp(temp.Text(), "img", strlen("img"))) *p = '\0'; if (!strncmp(temp.Text(), "iframe", strlen("iframe"))) *p = '\0'; } fRequest.ReplaceBase( "cl", client->Text() ); if( fRequest.GetViewMode() == VM_WORKSPACE ) ++workspaceCmd; } if( !pageContent ) fRequest.ReplaceBase( "pc", NULL ); else { int pageContentLimit = atoi( pageContent->Text() ); if( pageContentLimit <= 0 || pageContentLimit == fRequest.PageContentDefault() ) { fRequest.ReplaceBase( "pc", NULL ); } else { StrNum i; i.Set(pageContentLimit); fRequest.ReplaceBase( "pc", i.Text() ); } } if( !pageCache || !fRequest.GetBrowseMode() ) fRequest.ReplaceBase( "pgc", NULL ); else fRequest.ReplaceBase( "pgc", "y" ); if( !fixesAlways ) fRequest.ReplaceBase( "jf", NULL ); else fRequest.ReplaceBase( "jf", "y" ); if( !showLineNo ) fRequest.ReplaceBase( "lno", NULL ); else fRequest.ReplaceBase( "lno", "y" ); if( hideCols ) fRequest.ReplaceBase( "hd", hideCols->Text() ); if( browseOnly ) fRequest.ReplaceBase( "bo", browseOnly->Text() ); const StrPtr *M = fRequest.GetStateArg("M"); if( showP4Cmds ) { if (!M || !strchr(M->Text(), 'c')) { StrBuf newM; if (M) newM.Set(M); newM << "c"; fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } else if (M) { char *p; if (p = strchr(M->Text(), 'c')) { StrBuf newM; newM.Set(M); p = newM.Text() + (p - M->Text()); strcpy(p, p+1); newM.SetLength(); fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } if( showContentHist ) { if (!M || !strchr(M->Text(), 'h')) { StrBuf newM; if (M) newM.Set(M); newM << "h"; fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } else if (M) { char *p; if (p = strchr(M->Text(), 'h')) { StrBuf newM; newM.Set(M); p = newM.Text() + (p - M->Text()); strcpy(p, p+1); newM.SetLength(); fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } if( oldAnnotate ) { if (!M || !strchr(M->Text(), 'o')) { StrBuf newM; if (M) newM.Set(M); newM << "o"; fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } else if (M) { char *p; if (p = strchr(M->Text(), 'o')) { StrBuf newM; newM.Set(M); p = newM.Text() + (p - M->Text()); strcpy(p, p+1); newM.SetLength(); fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } if( eXperimental ) fRequest.ReplaceBase( "X", eXperimental->Text() ); if( screenChunks ) fRequest.ReplaceBase( "sho", screenChunks->Text() ); if( forceDefaults ) fRequest.ReplaceBase( "D", forceDefaults->Text() ); // // Set or unset the state diff flag parameter if( diffFlag || diffOutFlag ) { StrBuf dw; if( ( !diffFlag && !diffOutFlag ) || ( ( diffFlag && *diffFlag == "none" ) && ( diffOutFlag && *diffOutFlag == "none" ) ) ) { fRequest.ReplaceBase( "dw", NULL ); } else { if( diffFlag && *diffFlag != "none" ) dw << diffFlag; if( diffOutFlag && *diffOutFlag != "none" ) dw << diffOutFlag; fRequest.ReplaceBase( "dw", dw.Text() ); } } if( contextLines ) { if( *contextLines == "15" ) fRequest.ReplaceBase( "dc", NULL ); else { int cxli = atoi( contextLines->Text() ); if( cxli < 0 || cxli == 15 || (!cxli && *contextLines != "0") ) { fRequest.ReplaceBase( "dc", NULL ); } else { StrNum i; i.Set(cxli); fRequest.ReplaceBase( "dc", i.Text() ); } } } if( diffLiWrap ) { if( *diffLiWrap == "default" ) fRequest.ReplaceBase( "dl", NULL ); else fRequest.ReplaceBase( "dl", diffLiWrap->Text() ); } // // Set or unset the state resolve flag parameter if( resFlag ) { if( *resFlag == "none" ) fRequest.ReplaceBase( "rw", NULL ); else fRequest.ReplaceBase( "rw", resFlag->Text() ); } // // Set or unset the thumbnail parameters if( !thumbCols ) fRequest.ReplaceBase( "thc", NULL ); else { int thcols = atoi( thumbCols->Text() ); if( thcols < 1 || thcols == fRequest.GetThumbnailColsDefault() || thcols > 10 ) { fRequest.ReplaceBase( "thc", NULL ); } else { StrNum i; i.Set(thcols); fRequest.ReplaceBase( "thc", i.Text() ); } } if( thumbSize ) { if( *thumbSize == "none" ) fRequest.ReplaceBase( "thz", NULL ); else fRequest.ReplaceBase( "thz", thumbSize->Text() ); } if( !thumbMag ) fRequest.ReplaceBase( "thm", NULL ); else fRequest.ReplaceBase( "thm", "y" ); if( !thumbBorder ) fRequest.ReplaceBase( "thb", NULL ); else fRequest.ReplaceBase( "thb", "y" ); if( !thumbNoCSS ) fRequest.ReplaceBase( "thx", NULL ); else fRequest.ReplaceBase( "thx", "y" ); if( !thumbWrap ) fRequest.ReplaceBase( "thw", NULL ); else fRequest.ReplaceBase( "thw", "y" ); // // Reset password if( !fRequest.GetBrowseMode() && ( (newPass1 && newPass1->Length()) || (newPass2 && newPass2->Length()) || (oldPassword && oldPassword->Length()) ) ) { if( ( newPass1->Length() && !newPass2->Length() ) || ( !newPass1->Length() && newPass2->Length() ) ) { fError = 1; ErrorMsg.Set( "Error: Must type new password twice." ); } else if( newPass1->Length() && newPass2->Length() && ( *newPass1 != *newPass2 ) ) { fError = 1; ErrorMsg.Set( "Error: New password strings do not match." ); } else { ++passwdCmd; } } // // Save these settings as defaults if (defaults) fRequest.SetSaveDefaults(restore ? 2 : 1); } else if( cmd == AC_MULTIUSERPROCESSOR ) { if( fRequest.ProcessForm( spec , &specTable ) ) { client = specTable.GetVar( "Client" ); const StrPtr *save = specTable.GetVar( "save" ); newclient = specTable.GetVar( "newClient" ); fCreateBtn = specTable.GetVar( "create" ); const StrPtr *cliList = specTable.GetVar( "cliList" ); const StrPtr *cliListBtn = specTable.GetVar( "cliListBtn" ); // hack for MSIE to catch the case where the user entered a new client name // and then pressed the Enter key. if (newclient && !fCreateBtn && !client && !save && !cliList && !cliListBtn) fCreateBtn = (StrPtr *)newclient; if (cliListBtn) client = cliList; else if (fCreateBtn) client = NULL; if (!newclient || !newclient->Length()) fCreateBtn = NULL; if (fCreateBtn) client = newclient; Options *opts = fRequest.GetOpts(); if( client && client->Length() && ( *client != fRequest.GetClient() || (*opts)[ 'M' ] ) ) { fRequest.ReplaceBase( "cl", client->Text() ); if( fRequest.GetViewMode() == VM_WORKSPACE && !fCreateBtn ) ++workspaceCmd; } } } else if( cmd == AC_CLIENTSWITCH ) { if( fRequest.GetURL().Length() ) fRequest.ReplaceBase( "cl", fRequest.GetURL().Text() ); else fRequest.ReplaceBase( "cl", NULL ); if( fRequest.GetViewMode() == VM_WORKSPACE ) ++workspaceCmd; } else if( cmd == AC_EDITEXISTINGCLIENT ) { spec.Add( "editexistingyes" ); spec.Add( "editexistingno" ); if( fRequest.ProcessForm( spec , &specTable ) ) { StrPtr *yes = specTable.GetVar( "editexistingyes" ); StrPtr *no = specTable.GetVar( "editexistingno" ); if (!yes && !no) { fError = 1; return; } } else { fError = 1; return; } } else if( cmd == AC_DIFF21 ) { fRequest.ReplaceBase( "path", fRequest.GetPath().Text() ); if( fRequest.GetViewMode() == VM_WORKSPACE ) ++workspaceCmd; } else if( cmd == AC_DIFFSVR ) { fRequest.ReplaceBase( "path", fRequest.GetPath().Text() ); if( fRequest.GetViewMode() == VM_WORKSPACE ) ++workspaceCmd; if( fRequest.ProcessForm( spec, &specTable ) ) { if (!specTable.GetVar( "revs" )) { fError = 1; ErrorMsg.Set( "Before choosing the \"Diff vs. Selected Revision\" option, you must select a revision by clicking its radio button." ); return; } } } else if( cmd == AC_WORKSPACE ) { StrBuf buf; buf << fRequest.GetPath(); if (strcmp(buf.Text(), "//")) { p4wWherePane wherePane(*this, fRequest); char *p = buf.Text() + strlen(buf.Text()) - 1; if (*p == '/') buf << "x"; else buf << "/x"; fRequest.p4Arg( buf ); fRequest.p4( "where", 0, 0, &wherePane ); fRequest.p4Wait(); workPath.Set(wherePane.fLocalPath.Text()); if (wherePane.fError) { if( p4debug.GetLevel( DT_NET ) >= 1 ) printf(wherePane.fErrMsg.Text()); } else { p = workPath.Text() + strlen(workPath.Text()) - 1; if (*p == 'x') *p-- = '\0'; if (*p == '/' || *p == '\\') *p = '\0'; workPath.SetLength(); } } ++workspaceCmd; } else if( cmd == AC_DEPOTVIEW ) { StrBuf buf; buf << fRequest.GetPath(); p4wWherePane wherePane(*this, fRequest); char *p = buf.Text() + strlen(buf.Text()) - 1; if (*p == '/' || *p == '\\') buf << "x"; else buf << "/x"; #ifdef OS_NT fRequest.p4Arg( buf.Text() + 2 ); #else fRequest.p4Arg( buf.Text() + 1 ); #endif fRequest.p4( "where", 0, 0, &wherePane ); fRequest.p4Wait(); if (wherePane.fError) { buf.Set("//"); if( p4debug.GetLevel( DT_NET ) >= 1 ) printf(wherePane.fErrMsg.Text()); } else { buf.Set(wherePane.fDepotPath.Text()); p = buf.Text() + strlen(buf.Text()) - 1; if (*p == 'x') *p-- = '\0'; if (*p == '/') *p = '\0'; buf.SetLength(); } fRequest.ReplaceBase( "path", buf.Text() ); } else if( cmd == AC_GOTO ) { // // Goto path. Clean up the path if needed, and then // construct the url and relocate to it. const StrPtr *goField = NULL; StrBuf gotoPath; int isDepotMode = 0; int isDir = 1; // // Get the raw path entered on the form if( fRequest.ProcessForm( spec , &specTable ) ) { goField = specTable.GetVar( "goField" ); } else { fError = 1; return; } // // Normalize the path, remove ... if there char *end = NULL; if( goField && goField->Length() ) end = goField->Text() + goField->Length() - 1; if( !goField || !goField->Length() ) { gotoPath.Set( "//" ); } else if( goField->Length() > 2 && !strcmp( end - 2, "..." ) ) { gotoPath.Set( goField->Text(), goField->Length() - 3 ); } else { gotoPath.Set( goField ); } // // path is in workspace mode or not? if( gotoPath.Length() > 1 && gotoPath.Text()[0] == '/' && gotoPath.Text()[1] == '/' ) ++isDepotMode; // // path is a directory or a file? p4wURL urlMaker; char *node = urlMaker.GetNodeLocation( gotoPath.Text(), isDepotMode, AC_BROWSEFILE ); if( node && *node && !strstr( node, "..." ) ) { fNullPath = 1; isDir = 0; } // // New url is in perforce syntax, and old was in perforce syntax if( isDepotMode && fRequest.GetViewMode() != VM_WORKSPACE ) { if( isDir ) { fRequest.ReplaceBase( "cd", gotoPath.Text() ); fRequest.ReplaceBase( "cdf", NULL ); } else { fRequest.ReplaceBase( "cd", "//" ); fRequest.ReplaceBase( "cdf", gotoPath.Text() ); } fRequest.ReplaceBase( "path", gotoPath.Text() ); // // New url is in workpace syntax, and old was in perforce } else if( !isDepotMode && fRequest.GetViewMode() != VM_WORKSPACE ) { workPath.Set( gotoPath.Text() ); ++workspaceCmd; // // New url is in workspace syntax, so was old } else if( !isDepotMode && fRequest.GetViewMode() == VM_WORKSPACE ) { if( isDir ) { fRequest.ReplaceBase( "cd", gotoPath.Text() ); fRequest.ReplaceBase( "cdf", NULL ); } else { const StrPtr* wr1 = fRequest.GetStateArg( "wr" ); if( wr1 ) fRequest.ReplaceBase( "cd", wr1->Text() ); fRequest.ReplaceBase( "cdf", gotoPath.Text() ); } fRequest.ReplaceBase( "path", gotoPath.Text() ); // // New url is in perforce syntax, and old was in workspace mode } else if( isDepotMode && fRequest.GetViewMode() == VM_WORKSPACE ) { if( isDir ) { fRequest.ReplaceBase( "cd", gotoPath.Text() ); fRequest.ReplaceBase( "cdf", NULL ); } else { fRequest.ReplaceBase( "cd", "//" ); fRequest.ReplaceBase( "cdf", gotoPath.Text() ); } fRequest.ReplaceBase( "md", "c" ); fRequest.ReplaceBase( "wr", NULL ); fRequest.ReplaceBase( "path", gotoPath.Text() ); } } // // If we are switching to workspace mode or are resetting the client, // issue the info command to get the workspace root. Or invoke the // passwd command if user is changing password. if( !workspaceCmd && !passwdCmd ) return; // // If we are switching clients, start right now before issuing // any subsequent commands if( cmd == AC_CLIENTSWITCH && fRequest.GetURL().Length() ) { fRequest.GetClientApi().SetClient( fRequest.GetURL().Text() ); } else if( (cmd == AC_CONFIGPROCESSOR || cmd == AC_MULTIUSERPROCESSOR) && client ) { fRequest.GetClientApi().SetClient( client->Text() ); } // // Issue client Init() call here since we haven't issued // one yet. Error e; fRequest.p4Init( &e ); if( e.Test() ) { e.Fmt( &ErrorMsg ); fError = 1; return; } // // Invoke "p4 info" to get client root if we're in, or // switching to workspace mode if( workspaceCmd ) { if( workPath.Length() ) doWorkspaceCmd( cmd, workPath.Text() ); else doWorkspaceCmd( cmd ); } // // Invoke "p4 passwd" if user is changing/setting password const char *newPassword = NULL; if( newPass1 && newPass1->Length() ) newPassword = newPass1->Text(); if( passwdCmd ) { if( oldPassword && oldPassword->Length() ) doPasswdCmd( oldPassword->Text(), newPassword ); else doPasswdCmd( NULL, newPassword ); } fRequest.p4Final( &e ); } p4wRelocate::~p4wRelocate() { } int p4wRelocate::DoRelocate() { // // Generate a location URL and send a page with the location // directive UNLESS the URL is ready for mime content display as-is. if( generateURL() ) { if ( !sendPage() ) return 0; return 1; } return 0; } int p4wRelocate::generateURL() { // // Parse form or url to get parameters for the URL, and then // construct the URL appropriate for the command. If URL // is ready for mime display (ie it doesn't have anything to // remap in the url), do nothing and return 0. Spec spec; StrBufDict specTable; StrBufDict args; p4wURL urlMaker; switch( fCommand ) { // // Parse the filter form on the Path Browser page case AC_DEPOTPROCESSOR: { spec.Add( "fileFilter" ); spec.Add( "filter" ); spec.Add( "pattern" ); spec.Add( "showDeleted" ); spec.Add( "showClient" ); spec.Add( "incSubfolders" ); if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } StrPtr *clear = specTable.GetVar( "Clear" ); StrPtr *fileFilter = specTable.GetVar( "fileFilter" ); StrPtr *filter = specTable.GetVar( "filter" ); StrPtr *pattern = specTable.GetVar( "pattern" ); StrPtr *showDeleted = specTable.GetVar( "showDeleted" ); StrPtr *showClient = specTable.GetVar( "showClient" ); StrPtr *subfolders = specTable.GetVar( "incSubfolders" ); // // Radio option for the menu was chosen if( *fileFilter == "menu" || clear) { fCommand = (AllCommands)atoi( filter->Text() ); fRequest.ReplaceBase( "pat", NULL ); fRequest.ReplaceBase( "is", NULL ); // // Handle the various flavors of Path Browser mode // here if possible if( fCommand == AC_PATHOPENED || clear ) { fRequest.ReplaceBase( "po", NULL ); fRequest.ReplaceBase( "cf", NULL ); fRequest.ReplaceBase( "pb", NULL ); fCommand = AC_PATHBROWSER; } else if( fCommand == AC_PATHNOOPEN ) { fRequest.ReplaceBase( "po", "h" ); fRequest.ReplaceBase( "cf", NULL ); fRequest.ReplaceBase( "pb", NULL ); fCommand = AC_PATHBROWSER; } else if( fCommand == AC_PATHNOCURRENT ) { fRequest.ReplaceBase( "cf", "h" ); fRequest.ReplaceBase( "po", NULL ); fRequest.ReplaceBase( "pb", NULL ); fCommand = AC_PATHBROWSER; } else { fRequest.ReplaceBase( "pb", filter->Text() ); fRequest.ReplaceBase( "cf", NULL ); fRequest.ReplaceBase( "po", NULL ); fCommand = AC_PATHBROWSER; } // // Radio option for Files Matching was chosen } else { fCommand = AC_FILESMATCHING; if( pattern ) { fRequest.ReplaceBase( "pat", ( !pattern || *pattern == "" ) ? "*" : pattern->Text() ); fRequest.ReplaceBase( "po", NULL ); fRequest.ReplaceBase( "cf", NULL ); fRequest.ReplaceBase( "pb", NULL ); // Parse pattern to see if we have a symbolic // rev arg (sr) char *sr = strchr( pattern->Text(), '@' ); if( sr ) args.SetVar( "sr", sr + 1 ); if( subfolders ) fRequest.ReplaceBase( "is", "y" ); else fRequest.ReplaceBase( "is", NULL ); } else { fRequest.ReplaceBase( "pat", NULL ); fRequest.ReplaceBase( "is", NULL ); } } // // Process the show client & show deleted files checkboxes if( clear ) { fRequest.ReplaceBase( "md", fRequest.GetBrowseMode() ? "d" : "c" ); } else if( showClient ) { fRequest.ReplaceBase( "md", "c" ); } else { if( fRequest.GetViewMode() != VM_WORKSPACE ) fRequest.ReplaceBase( "md", "d" ); } if( showDeleted && !clear ) { if( fRequest.HideDeletedFiles() ) fRequest.ReplaceBase( "df", "s" ); } else { if( !fRequest.HideDeletedFiles() ) fRequest.ReplaceBase( "df", NULL ); } urlMaker.ConstructLocationURL( fNewURL, NULL, fCommand, &args, fRequest.GetUnicode() ); } break; case AC_CONFIGPROCESSOR: { if( fError ) { return 0; } // // All the real work is done in the constructor. This builds // the URL with the new flags in place. // char *urlPath; if( fNullPath ) urlPath = NULL; else urlPath = fRequest.GetURL().Text(); // // Setting the pw flag forces p4web to prompt for password. // Do this if the password was changed. If the password was // deleted, don't re-prompt: let the next command catch // the error. if( fPasswordSet && fNewPassword.Length() ) args.SetVar( "pw", "1" ); urlMaker.ConstructLocationURL( fNewURL, urlPath, AC_CONFIGURATION, &args, fRequest.GetUnicode() ); } break; case AC_MULTIUSERPROCESSOR: { if( fError ) { return 0; } // // All the real work is done in the constructor. This builds // the URL with the new flags in place. // if (fCreateBtn) { StrBuf base; base.Set(fRequest.GetBase()); char *p = strrchr(base.Text(), '@'); if (p && *++p == '/') { *p = '\0'; base.SetLength(); fRequest.SetBase(base.Text()); } urlMaker.ConstructURL( fNewURL, NULL, AC_EDITNEWCLIENT, NULL, fRequest.GetUnicode() ); fRequest.SetCr8NewClient(1); } else { char *urlPath; if( fNullPath ) urlPath = NULL; else urlPath = fRequest.GetURL().Text(); char *p = NULL; AllCommands cmd = AC_PATHBROWSER; const StrPtr * referer = fRequest.GetReferer(); if (referer) { p = strstr(referer->Text(), "?ac="); if (p) cmd = (AllCommands)atoi(p + sizeof("?ac=") - 1); if (cmd == AC_MULTIUSER) cmd = AC_PATHBROWSER; p = NULL; } urlMaker.ConstructLocationURL( fNewURL, urlPath, cmd, &args, fRequest.GetUnicode() ); if (p && (p = strchr(p + sizeof("?ac="), '&'))) fNewURL << p; } } break; case AC_GOTO: { if( fError ) { return 0; } // // All real work was done in the constructor, so // just construct the url if( !fNullPath ) urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); else urlMaker.ConstructLocationURL( fNewURL, NULL, AC_BROWSEFILE, &args, fRequest.GetUnicode() ); } break; case AC_FIXPROCESSOR: { char *postdata = fRequest.GetPostData(); if (!postdata) return 0; StrPtr sp = fRequest.GetURL(); if (*postdata == 's') args.SetVar( "mx", "50" ); args.SetVar( "jb", sp ); urlMaker.ConstructLocationURL( fNewURL, NULL, *postdata == 's' ? AC_FIXSUBMITTED : AC_FIXPENDING, &args, fRequest.GetUnicode() ); } break; case AC_CLIENTSWITCH: { // // All the real work (setting up the base) was done in the // constructor. urlMaker.ConstructLocationURL( fNewURL, NULL, AC_CLIENTSWITCHRES, &args, fRequest.GetUnicode() ); } break; case AC_EDITEXISTINGCLIENT: { spec.Add( "editexistingyes" ); spec.Add( "editexistingno" ); if( fRequest.ProcessForm( spec , &specTable ) ) { StrPtr *yes = specTable.GetVar( "editexistingyes" ); StrPtr *no = specTable.GetVar( "editexistingno" ); if (yes) { urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); } else { urlMaker.ConstructLocationURL( fNewURL, NULL, AC_MULTIUSER, &args, fRequest.GetUnicode() ); } } } break; case AC_DIFF21: { const StrPtr *rev1 = fRequest.GetDynArg( "rev1" ); if (rev1) { StrBuf temp; temp << atoi(rev1->Text()) - 1; args.SetVar( "rev1", temp ); args.SetVar( "rev2", rev1 ); } StrBuf path; int workspaceCmd = 0; if( fRequest.GetViewMode() == VM_WORKSPACE ) { path << fRequest.GetURL(); workspaceCmd++; } urlMaker.ConstructLocationURL( fNewURL, workspaceCmd ? path.Text() : NULL, AC_DIFF2, &args, fRequest.GetUnicode() ); } break; case AC_DIFF22: { if( fRequest.GetStateArg( "cdf" ) ) return 0; const StrPtr *file1 = fRequest.GetDynArg( "fil1" ); if (!file1 || !file1->Length()) return 0; const StrPtr *file2 = fRequest.GetDynArg( "fil2" ); if (!file2 || !file2->Length()) return 0; fRequest.ReplaceBase( "cdf", file2->Text() ); fRequest.ReplaceBase( "path", file2->Text() ); args.SetVar( "fil1", file1 ); args.SetVar( "fil2", file2 ); const StrPtr *rev1 = fRequest.GetDynArg( "rev1" ); if (rev1 && rev1->Length()) args.SetVar( "rev1", rev1 ); else { const StrPtr *sr1 = fRequest.GetDynArg( "sr1" ); if (sr1 && sr1->Length()) args.SetVar( "sr1", sr1 ); } const StrPtr *rev2 = fRequest.GetDynArg( "rev2" ); if (rev2 && rev2->Length()) args.SetVar( "rev2", rev2 ); else { const StrPtr *sr2 = fRequest.GetDynArg( "sr2" ); if (sr2 && sr2->Length()) args.SetVar( "sr2", sr2 ); } urlMaker.ConstructLocationURL( fNewURL, NULL, AC_DIFF22, &args, fRequest.GetUnicode() ); } break; case AC_DIFF2FILESPROCESSOR: { spec.Add( "File1" ); spec.Add( "File2" ); spec.Add( "Rev1" ); spec.Add( "Rev2" ); spec.Add( "revVal1" ); spec.Add( "revVal2" ); spec.Add( "atChangeVal1" ); spec.Add( "atChangeVal2" ); spec.Add( "atVal1" ); spec.Add( "atVal2" ); if( !fRequest.ProcessForm( spec, &specTable ) ) return 0; StrPtr *file1 = specTable.GetVar( "File1" ); StrPtr *file2 = specTable.GetVar( "File2" ); StrPtr *rev1 = specTable.GetVar( "Rev1" ); StrPtr *rev2 = specTable.GetVar( "Rev2" ); StrPtr *revval1 = specTable.GetVar( "revVal1" ); StrPtr *revval2 = specTable.GetVar( "revVal2" ); StrPtr *revchg1 = specTable.GetVar( "atChangeVal1" ); StrPtr *revchg2 = specTable.GetVar( "atChangeVal2" ); StrPtr *revat1 = specTable.GetVar( "atVal1" ); StrPtr *revat2 = specTable.GetVar( "atVal2" ); StrPtr *revdate1 = specTable.GetVar( "dateVal1" ); StrPtr *revdate2 = specTable.GetVar( "dateVal2" ); if (!file1 || !file2) return 0; int pathOK = 0; if (strcmp(file1->Text(), fRequest.GetPath().Text())) args.SetVar( "fil1", file1 ); else pathOK = 1; if (strcmp(file2->Text(), fRequest.GetPath().Text())) args.SetVar( "fil2", file2 ); else pathOK = 1; if (rev1) { if (*rev1 == "rev") { if (revval1 && revval1->Length()) args.SetVar( "rev1", revval1->Text() ); } else if (*rev1 == "atChange") { if (revchg1 && revchg1->Length()) args.SetVar( "sr1", revchg1->Text() ); } else if (*rev1 == "at") { if (revat1 && revat1->Length()) args.SetVar( "sr1", revat1->Text() ); } else if (*rev1 == "date") { if (revdate1 && revdate1->Length()) args.SetVar( "sr1", revdate1->Text() ); } else if (*rev1 == "have") { args.SetVar( "rev1", "have" ); } } if (rev2) { if (*rev2 == "rev") { if (revval2 && revval2->Length()) args.SetVar( "rev2", revval2->Text() ); } else if (*rev2 == "atChange") { if (revchg2 && revchg2->Length()) args.SetVar( "sr2", revchg2->Text() ); } else if (*rev2 == "at") { if (revat2 && revat2->Length()) args.SetVar( "sr2", revat2->Text() ); } else if (*rev2 == "date") { if (revdate2 && revdate2->Length()) args.SetVar( "sr2", revdate2->Text() ); } else if (*rev2 == "have") { args.SetVar( "rev2", "have" ); } } if (strchr( file1->Text(), '*' ) || strstr( file1->Text(), "..." ) || strchr( file2->Text(), '*' ) || strstr( file2->Text(), "..." )) { char temp[2] = "?"; StrBuf common; char *p = file1->Text(); char *q = file2->Text(); while (*p == *q && *p != '*') { temp[0] = *p++; common.Append(temp); q++; } p = strrchr(common.Text(), '/'); if (p) { *p++ = '\0'; common.SetLength(); } #ifdef OS_NT else if( fRequest.GetViewMode() == VM_WORKSPACE ) { p = strrchr(common.Text(), '\\'); if (p) { *p++ = '\0'; common.SetLength(); } else common.Set("//"); } #endif else common.Set("//"); fRequest.ReplaceBase( "path", common.Text() ); if (strstr(fRequest.GetBase().Text(), "&cdf=")) fRequest.ReplaceBase( "cdf", NULL ); urlMaker.ConstructLocationURL( fNewURL, NULL, AC_DIFF2DIRSOUTPUT, &args, fRequest.GetUnicode() ); } else { if (!pathOK && file2->Length()) { fRequest.ReplaceBase( "cdf", file2->Text() ); fRequest.ReplaceBase( "path", file2->Text() ); } urlMaker.ConstructLocationURL( fNewURL, (pathOK || !file2->Length()) ? fRequest.GetURL().Text() : NULL, AC_DIFF22, &args, fRequest.GetUnicode() ); } } break; case AC_DIFFSVR: { if( fError ) return 0; if( fRequest.ProcessForm( spec, &specTable ) ) { const StrPtr *rev1 = specTable.GetVar( "revs" ); const StrPtr *rev2 = specTable.GetVar( "rev2" ); if (rev1 && rev2) { args.SetVar( "rev1", rev1 ); args.SetVar( "rev2", rev2 ); } } StrBuf path; int workspaceCmd = 0; if( fRequest.GetViewMode() == VM_WORKSPACE ) { path << fRequest.GetURL(); workspaceCmd++; } urlMaker.ConstructLocationURL( fNewURL, workspaceCmd ? path.Text() : NULL, AC_DIFF2, &args, fRequest.GetUnicode() ); } break; case AC_ANNOTATE: case AC_FULLANNOTATE: case AC_CHGLISTANNOTATE: case AC_CHGLISTFULLANNOTATE: { const StrPtr *mu = fRequest.GetDynArg( "mu" ); const StrPtr *rev1 = fRequest.GetDynArg( "rev1" ); if (!mu || !rev1) return 0; // remove both mu and rev1 which are not needed // as they are artifacts of the JS popup menus StrBuf path; path << fRequest.GetURL(); urlMaker.ConstructLocationURL( fNewURL, path.Text(), fCommand, &args, fRequest.GetUnicode() ); } break; case AC_GENERALANNOTATE: { // remove both mu and rev1 which are not needed // as they are artifacts of the JS popup menus const StrPtr *mu = fRequest.GetDynArg( "mu" ); const StrPtr *rev1 = fRequest.GetDynArg( "rev1" ); StrBuf path; path << fRequest.GetURL(); // check the "M" state arg to determine // which flavor of annotate needs to be run const StrPtr *M = fRequest.GetStateArg("M"); if (M && strchr(M->Text(), 'o')) // old style annotate? fCommand = (M && strchr(M->Text(), 'd')) ? AC_FULLANNOTATE : AC_ANNOTATE; else fCommand = (M && strchr(M->Text(), 'd')) ? AC_CHGLISTFULLANNOTATE : AC_CHGLISTANNOTATE; urlMaker.ConstructLocationURL( fNewURL, path.Text(), fCommand, &args, fRequest.GetUnicode() ); } break; case AC_WORKSPACE: case AC_DEPOTVIEW: { // All work was done in the constructor if( fError ) return 0; urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); } break; case AC_BROWSEFILE: { const StrPtr *cdf = fRequest.GetStateArg( "cdf" ); if( cdf || fError ) return 0; fRequest.ReplaceBase( "cdf", fRequest.GetPath().Text() ); fRequest.ReplaceBase( "path", fRequest.GetPath().Text() ); fNewURL.Set( fRequest.GetDynURL() ); } break; case AC_MENUPROCESSOR: { // // Determine exact request as specified in viewValue StrBufDict itemTable; spec.Add( "viewValue" ); if( !fRequest.ProcessForm( spec, &itemTable ) ) return 0; fNewURL.Set( itemTable.GetVar( "viewValue" )->Text() ); } break; case AC_JOBSPROCESSOR: { // // Parse spec table to get the form's values for // max # jobs, job filter, view in ascending order, // view jobs fixed in path, and view jobs including // integrations. int bSaveDefs = 2; spec.Add( "Max" ); spec.Add( "Filter" ); spec.Add( "Asc" ); spec.Add( "Fp" ); spec.Add( "Integ" ); spec.Add( "Jsf" )->type = SDT_LLIST; // // If post data is missing return immediately. if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Parse the form elements to generate the url StrPtr *clear = specTable.GetVar( "Clear" ); StrPtr *maxValue = specTable.GetVar( "Max" ); StrPtr *filterValue = specTable.GetVar( "Filter" ); StrPtr *ascValue = specTable.GetVar( "Asc" ); StrPtr *fpValue = specTable.GetVar( "Fp" ); StrPtr *integValue = specTable.GetVar( "Integ" ); const char *path = NULL; if( clear ) args.SetVar( "mx", "25" ); else if( maxValue && atoi( maxValue->Text() ) ) args.SetVar( "mx", maxValue ); const StrPtr *pcl = fRequest.GetDynArg( "pcl" ); if ( pcl && pcl->Length() ) args.SetVar( "pcl", pcl ); const StrPtr *sr = fRequest.GetDynArg( "sr" ); if ( sr && sr->Length() ) args.SetVar( "sr", sr ); if( filterValue && filterValue->Length() && !clear ) { args.SetVar( "ft", filterValue ); bSaveDefs = 1; } if( ascValue && *ascValue == "lo" && !clear ) args.SetVar( "jasc", "1" ); if( fpValue && !clear ) args.SetVar( "jfp", "1" ); if( integValue && !clear ) { args.SetVar( "jin", "1" ); if( !fpValue ) args.SetVar( "jfp", "1" ); // jin implies jfp } StrPtr *s; for( int i = 0; ( s = specTable.GetVar( ( StrRef )"Jsf", i ) ) != NULL; i++ ) { args.SetVar( "jsf", i, *s ); bSaveDefs = 1; } if( fRequest.GetURL().Length() ) path = fRequest.GetURL().Text(); urlMaker.ConstructLocationURL( fNewURL, path, AC_JOBS, &args, fRequest.GetUnicode() ); if ( !pcl || !pcl->Length() ) fRequest.SetSaveJobsDefs(bSaveDefs); } break; case AC_SHOWHIDEJOBCOLS: { int i; char *p; StrBuf dynargs; const StrPtr *show = fRequest.GetDynArg("show"); const StrPtr *hide = fRequest.GetDynArg("hide"); const StrPtr *referer = fRequest.GetReferer(); if (referer) // get the dyn args from the referer { p = strstr(referer->Text(), "?ac="); if (p) { p = strchr(p, '&'); if (p) dynargs << p; } } else // if no referer, try the P4WJobsDefs cookie { const StrPtr *cookie = fRequest.GetCookies(); if (cookie && (p = strstr(cookie->Text(), "P4WJobsDefs=")) ) { StrBuf temp; temp.Set(p + sizeof("P4WJobsDefs=")-1); char *q = strstr(temp.Text(), "; "); if (q) { *q = '\0'; temp.SetLength(); } dynargs << temp; } } // if any &jsf values were passed in with this URL // add them to the dyn args const StrPtr *sp; for( i = -1; ( sp = fRequest.GetDynArg( "jsf", ++i ) ) != NULL; ) dynargs << "&jsf=" << sp; if (dynargs.Length()) // chg the dynargs to reflect the show/hide { if (show) dynargs << "&jsf=" << show; else if (hide) { StrBuf look4; look4 << "&jsf=" << hide; p = strstr(dynargs.Text(), look4.Text()); if (p) { char *q = strchr(p+5, '&'); if (q) strcpy(p, q); else *p = '\0'; dynargs.SetLength(); } } } fNewURL << "?ac=" << AC_JOBS << dynargs; fRequest.SetSaveJobsDefs(1); } break; case AC_SUBMITTEDCHANGELISTSFILE: case AC_SUBMITTEDCHANGELISTS: case AC_BRANCHES: case AC_LABELS: case AC_LABELSPATH: case AC_CLIENTS: case AC_USERS: case AC_JOBS: { if (!fRequest.GetDefaults().Length()) return 0; const char *path = NULL; const StrPtr dynurl = fRequest.GetDynURL(); char *p = strchr(dynurl.Text(), '&'); if (fCommand == AC_JOBS) { if (!p || strcmp(p, "&mx=25") || !strcmp(p, fRequest.GetDefaults().Text())) return 0; } else if (fCommand == AC_SUBMITTEDCHANGELISTS || fCommand == AC_SUBMITTEDCHANGELISTSFILE) { if (!p || strcmp(p, "&mx=50") || !strcmp(p, fRequest.GetDefaults().Text())) return 0; } else if (p) return 0; if ( fCommand == AC_SUBMITTEDCHANGELISTSFILE ) { StrBuf newBase; path = fRequest.GetReturnURL( fRequest.GetLastReturnType() ).Text(); fRequest.UseNewBase( newBase, NULL, "path", path ); fRequest.SetBase(newBase.Text()); path = NULL; } else if( fRequest.GetURL().Length() && fCommand != AC_SUBMITTEDCHANGELISTS ) path = fRequest.GetURL().Text(); StrBuf defs; defs << fRequest.GetDefaults().Text(); switch(fCommand) { case AC_BRANCHES: fRequest.RmvDynArgBeginWith(defs, 'c'); fRequest.RmvDynArgBeginWith(defs, 'l'); fRequest.RmvDynArgBeginWith(defs, 'u'); break; case AC_CLIENTS: fRequest.RmvDynArgBeginWith(defs, 'b'); fRequest.RmvDynArgBeginWith(defs, 'l'); fRequest.RmvDynArgBeginWith(defs, 'u'); break; case AC_LABELS: case AC_LABELSPATH: fRequest.RmvDynArgBeginWith(defs, 'b'); fRequest.RmvDynArgBeginWith(defs, 'c'); fRequest.RmvDynArgBeginWith(defs, 'u'); if (fCommand == AC_LABELSPATH) { char *p = strstr(defs.Text(), "&lfl=2"); if (p) { strcpy(p, p + sizeof("&lfl=2")-1); defs.SetLength(); } } break; case AC_USERS: fRequest.RmvDynArgBeginWith(defs, 'b'); fRequest.RmvDynArgBeginWith(defs, 'c'); fRequest.RmvDynArgBeginWith(defs, 'l'); break; default: break; } defs.SetLength(); if (!defs.Length()) return 0; if (fCommand == AC_LABELS) { p = strstr(defs.Text(), "&lfl="); if (p && (*(p+sizeof("&lfl=")-1) & 2)) { fCommand = AC_LABELSPATH; if (*(p+sizeof("&lfl=")-1) == '2') { strcpy(p, p + sizeof("&lfl=2")-1); defs.SetLength(); } } } urlMaker.ConstructLocationURL( fNewURL, path, fCommand, &args, fRequest.GetUnicode() ); fNewURL << defs; // add the cookie info to the ac } break; case AC_CHANGESPROCESSOR: case AC_FIXSUBPROCESSOR: { // // Parse a spec table to get the form's values for max # changes, // whether to include integrated changes, range, and/or file pattern spec.Add( "Max" ); spec.Add( "Int" ); spec.Add( "UpToVal" ); spec.Add( "PatVal" ); spec.Add( "IsFile" ); spec.Add( "User" ); spec.Add( "Client" ); spec.Add( "AllC" ); // // If post data is missing return immediately. if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Parse the form elements to generate the url int bSaveDefs = 2; StrPtr *clear = specTable.GetVar( "Clear" ); StrPtr *maxValue = specTable.GetVar( "Max" ); StrPtr *intValue = specTable.GetVar( "Int" ); StrPtr *nextValue = specTable.GetVar( "UpToVal" ); StrPtr *patValue = specTable.GetVar( "PatVal" ); StrPtr *isFile = specTable.GetVar( "IsFile" ); StrPtr *user = specTable.GetVar( "User" ); StrPtr *client = specTable.GetVar( "Client" ); StrPtr *allC = specTable.GetVar( "AllC" ); AllCommands ac = ( isFile ? AC_SUBMITTEDCHANGELISTSFILE : fRequest.GetCmd() == AC_FIXSUBPROCESSOR ? AC_FIXSUBMITTED : AC_SUBMITTEDCHANGELISTS); const StrPtr *jb = fRequest.GetDynArg( "jb" ); if ( jb && jb->Length() ) args.SetVar( "jb", jb ); if( intValue && !clear) { args.SetVar( "fl", intValue ); bSaveDefs = 1; } if( clear ) args.SetVar( "mx", "50" ); else if( maxValue && atoi( maxValue->Text() ) ) { args.SetVar( "mx", maxValue ); if (atoi( maxValue->Text() ) != 50) bSaveDefs = 1; } if( !allC && !clear) { args.SetVar( "al", "y" ); bSaveDefs = 1; } if( user && user->Length() && !clear ) { args.SetVar( "u", user ); bSaveDefs = 1; } if( client && client->Length() && !clear ) { args.SetVar( "cl", client ); bSaveDefs = 1; } if( patValue && patValue->Length() && !clear && ( strcmp( patValue->Text(), "..." ) ) ) fRequest.ReplaceBase( "pat", patValue->Text() ); // // If the user explicitly clears an existing // pattern, we need to unset the pat state // variable to make it go away. else if( fRequest.GetStateArg( "pat" ) ) fRequest.ReplaceBase( "pat", NULL ); if( nextValue->Length() && !clear ) { StrBuf r1; StrBuf r2; const char *loc = NULL; const char *v1; const char *v2; char field; // // Hash: numeric revision. At sign: symbolic rev. // Neither: symbolic rev by default. // If comma is found, this will be a range of // submitted changelists if( *nextValue->Text() == '#' ) { loc = nextValue->Text() + 1; field = '#'; v1 = "rev1"; v2 = "rev2"; } else { if( *nextValue->Text() == '@' ) loc = nextValue->Text() + 1; else loc = nextValue->Text(); field = '@'; v1 = "sr"; v2 = "sr2"; } const char *arg2 = strchr( loc, ',' ); if( arg2 && *(arg2 + 1) ) { r1.Set( loc, arg2 - loc ); if( *(arg2 + 1) == field ) arg2 += 2; else ++arg2; args.SetVar( v1, r1 ); if( *arg2 ) { r2.Set( arg2 ); args.SetVar( v2, r2 ); } } else { r1.Set( loc ); args.SetVar( v1, r1 ); } bSaveDefs = 1; } urlMaker.ConstructLocationURL( fNewURL, fRequest.GetURL().Text(), ac, &args, fRequest.GetUnicode() ); if (bSaveDefs != 2 || fRequest.GetDefaults().Length()) fRequest.SetSaveChgsDefs(bSaveDefs); } break; case AC_DELETECONFPROC: { // // Parse the formActions value to get the correct // command to run SpecElem * se = spec.Add( "formActions" ); se->type = SDT_LLIST; if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Loop through list of possible form action values StrPtr * chosenAction = NULL; StrPtr * a = NULL; for( int ca = 0; (a = specTable.GetVar( StrRef( "formActions" ), ca ) ) != NULL; ca++ ) { // See if this action is the one that was selected. Spec as; StrBufDict ast; as.Add( *a ); (void)fRequest.ProcessForm( as, &ast ); chosenAction = ast.GetVar( a->Text() ); if( chosenAction != NULL ) { chosenAction = a; break; } } if( chosenAction == NULL ) { remapBogusURL(); return 1; } // // Generate the url based on the chosen action StrBuf path; if( *chosenAction == "job" ) { fCommand = AC_JOBVIEW; path << fRequest.GetURL(); } else if( *chosenAction == "label" ) { fCommand = AC_LABELVIEW; path << fRequest.GetURL(); } else if( *chosenAction == "branch" ) { fCommand = AC_BRANCHVIEW; path << fRequest.GetURL(); } else if( *chosenAction == "file" ) { fCommand = AC_BROWSEFILE; path << fRequest.GetURL(); } else if( *chosenAction == "path" ) { fCommand = AC_PATHBROWSER; } else if( *chosenAction == "deleteJob" ) { fCommand = AC_DELETEJOB; path << fRequest.GetURL(); } else if( *chosenAction == "deleteLabel" ) { fCommand = AC_DELETELABEL; path << fRequest.GetURL(); } else if( *chosenAction == "deleteBranch" ) { fCommand = AC_DELETEBRANCH; path << fRequest.GetURL(); } else if( *chosenAction == "revert" ) { fCommand = AC_REVERTCMD; path << fRequest.GetURL(); } else { remapBogusURL(); return 1; } urlMaker.ConstructLocationURL( fNewURL, path.Text(), fCommand, &args, fRequest.GetUnicode() ); } break; case AC_SHOWHIDECOLSPROC: { if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } const StrPtr *showhidecols = specTable.GetVar( "showhidecols"); const StrPtr *javascript = specTable.GetVar( "javascript" ); if (!showhidecols) { if (javascript) { fClose = 1; return 0; } remapBogusURL(); return 1; } int showhide = 0; const StrPtr *shRev = specTable.GetVar( "shRev" ); const StrPtr *shType = specTable.GetVar( "shType" ); const StrPtr *shNewType = specTable.GetVar( "shNewType" ); const StrPtr *shOtherOpen = specTable.GetVar( "shOtherOpen" ); const StrPtr *shSize = specTable.GetVar( "shSize" ); const StrPtr *shChg = specTable.GetVar( "shChg" ); const StrPtr *shAction = specTable.GetVar( "shAction" ); const StrPtr *shDate = specTable.GetVar( "shDate" ); const StrPtr *shTime = specTable.GetVar( "shTime" ); const StrPtr *shYourChg = specTable.GetVar( "shYourChg" ); const StrPtr *shYourAction = specTable.GetVar( "shYourAction" ); const StrPtr *shOtherChg = specTable.GetVar( "shOtherChg" ); const StrPtr *shOtherAction = specTable.GetVar( "shOtherAction" ); const StrPtr *shOtherUser = specTable.GetVar( "shOtherUser" ); const StrPtr *shOtherClient = specTable.GetVar( "shOtherClient" ); int coMingle = fRequest.GetBrowseMode(); if (coMingle) { shYourChg = shOtherChg; shYourAction = shOtherAction; } if (!shRev) showhide += HIDE_REV; if (!shType) showhide += HIDE_TYPE; if (!shNewType) showhide += HIDE_NEWTYPE; if (!shOtherOpen) showhide += HIDE_OTHEROPEN; if (!shSize) showhide += HIDE_SIZE; if (!shChg) showhide += HIDE_CHG; if (!shAction) showhide += HIDE_ACTION; if (!shDate) showhide += HIDE_DATE; if (!shTime) showhide += HIDE_TIME; if (!shYourChg) showhide += HIDE_YOURCHG; if (!shYourAction) showhide += HIDE_YOURACTION; if (!shOtherChg) showhide += HIDE_OTHERCHG; if (!shOtherAction) showhide += HIDE_OTHERACTION; if (!shOtherUser) showhide += HIDE_OTHERUSER; if (!shOtherClient) showhide += HIDE_OTHERCLIENT; StrBuf newhd; newhd << showhide; fRequest.ReplaceBase( "hd", showhide ? newhd.Text() : NULL ); urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); if (javascript) { fLoadUrl = 1; StrBuf location; if( fRequest.GetJavascriptMode() == 2 ) location << p4wStrBuf().NormalizeBase( fRequest.GetBase(), 0 ); else location << p4wStrBuf().NormalizeBase( fRequest.GetBase(), fRequest.GetUnicode() ); location << fNewURL; fNewURL.Set(location); return 0; } } break; case AC_SHOWHIDEFILECOLS: { int showhide = 0; const StrPtr *hd = fRequest.GetStateArg("hd"); if (hd) showhide = atoi(hd->Text()); const StrPtr *show = fRequest.GetDynArg("show"); const StrPtr *hide = fRequest.GetDynArg("hide"); if (hide) showhide += atoi(hide->Text()); else if (show) { int n = atoi(show->Text()); int currentlyhiding = n & showhide; if (currentlyhiding) showhide -= currentlyhiding; } StrBuf newhd; newhd << showhide; fRequest.ReplaceBase( "hd", showhide ? newhd.Text() : NULL ); urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); } break; case AC_CHGLISTANNOTATEPROC: { spec.Add( "showUser" ); spec.Add( "Full" ); // // If post data is missing return immediately. if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Parse the form elements to generate the url const StrPtr *noDetails = specTable.GetVar( "noDetails" ); const StrPtr *showUser = specTable.GetVar( "showUser" ); const StrPtr *showRevNo = specTable.GetVar( "showRevNo" ); const StrPtr *showDelLi = specTable.GetVar( "showDelLi" ); const StrPtr *revRange = specTable.GetVar( "RevRange" ); const StrPtr *M = fRequest.GetStateArg("M"); if( showUser ) { if (!M || !strchr(M->Text(), 'u')) { StrBuf newM; if (M) newM.Set(M); newM << "u"; fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } else if (M) { char *p; if (p = strchr(M->Text(), 'u')) { StrBuf newM; newM.Set(M); p = newM.Text() + (p - M->Text()); strcpy(p, p+1); newM.SetLength(); fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } if( showRevNo && *showRevNo == "y" ) { if (!M || !strchr(M->Text(), 'r')) { StrBuf newM; if (M) newM.Set(M); newM << "r"; fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } else if (M) { char *p; if (p = strchr(M->Text(), 'r')) { StrBuf newM; newM.Set(M); p = newM.Text() + (p - M->Text()); strcpy(p, p+1); newM.SetLength(); fRequest.ReplaceBase( "M", newM.Text() ); M = fRequest.GetStateArg("M"); } } if( showDelLi ) { if (!M || !strchr(M->Text(), 'd')) { StrBuf newM; if (M) newM.Set(M); newM << "d"; fRequest.ReplaceBase( "M", newM.Text() ); } } else if (M) { char *p; if (p = strchr(M->Text(), 'd')) { StrBuf newM; newM.Set(M); p = newM.Text() + (p - M->Text()); strcpy(p, p+1); newM.SetLength(); fRequest.ReplaceBase( "M", newM.Text() ); } } if (revRange && revRange->Length()) { StrBuf r1; StrBuf r2; const char *loc = NULL; const char *v1; const char *v2; char field; // // Hash: numeric revision. At sign: symbolic rev. // Neither: symbolic rev by default. // If comma is found, this will be a range of // submitted changelists or revs if( *revRange->Text() == '#' ) { loc = revRange->Text() + 1; field = '#'; v1 = "rev1"; v2 = "rev2"; } else { if( *revRange->Text() == '@' ) loc = revRange->Text() + 1; else loc = revRange->Text(); field = '@'; v1 = "sr"; v2 = "sr2"; } const char *arg2 = strchr( loc, ',' ); if( arg2 && *(arg2 + 1) ) { r1.Set( loc, arg2 - loc ); if( *(arg2 + 1) == field ) arg2 += 2; else ++arg2; args.SetVar( v1, r1 ); if( *arg2 ) { r2.Set( arg2 ); args.SetVar( v2, r2 ); } } else { r1.Set( loc ); args.SetVar( v1, r1 ); } } if (noDetails) urlMaker.ConstructLocationURL( fNewURL, fRequest.GetURL().Text(), showDelLi ? AC_FULLANNOTATE : AC_ANNOTATE, &args, fRequest.GetUnicode() ); else urlMaker.ConstructLocationURL( fNewURL, fRequest.GetURL().Text(), showDelLi ? AC_CHGLISTFULLANNOTATE : AC_CHGLISTANNOTATE, &args, fRequest.GetUnicode() ); } break; case AC_BRANCHESPROCESSOR: { // // Parse a spec table to get the form's values // to determine how to filter spec.Add( "bfl" ); spec.Add( "bnm" ); spec.Add( "bow" ); spec.Add( "bdu" ); spec.Add( "bda" ); spec.Add( "Updated" ); spec.Add( "Accessed" ); char *val; if( fRequest.GetURL().Length() ) val = fRequest.GetURL().Text(); else val = NULL; // // If post data is missing return immediately. if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Parse the form elements to generate the url int bFilterDefs = fRequest.RmvDynArgBeginWith(fRequest.GetDefaults(), 'b'); if (!specTable.GetVar( "Clear" )) { StrBuf temp; const StrPtr *bfl = specTable.GetVar( "bfl" ); if ( bfl && bfl->Length() ) { args.SetVar( "bfl", bfl ); temp.Set(fRequest.GetDefaults()); temp << "&bfl=" << bfl; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *bnm = specTable.GetVar( "bnm" ); if ( bnm && bnm->Length() ) { args.SetVar( "bnm", bnm ); temp.Set(fRequest.GetDefaults()); temp << "&bnm=" << bnm; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *bow = specTable.GetVar( "bow" ); if ( bow && bow->Length() ) { args.SetVar( "bow", bow ); temp.Set(fRequest.GetDefaults()); temp << "&bow=" << bow; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *bdu = specTable.GetVar( "bdu" ); if ( bdu && bdu->Length() && strcmp(bdu->Text(), "yyyy/mm/dd") ) { const StrPtr *updated = specTable.GetVar( "Updated" ); StrBuf u; if (updated) { if (*updated == "on") u << "_"; else if (*updated == "before") u << "-"; } u << bdu; args.SetVar( "bdu", u ); temp.Set(fRequest.GetDefaults()); temp << "&bdu=" << u; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *bda = specTable.GetVar( "bda" ); if ( bda && bda->Length() && strcmp(bda->Text(), "yyyy/mm/dd") ) { const StrPtr *accessed = specTable.GetVar( "Accessed" ); StrBuf a; if (accessed) { if (*accessed == "on") a << "_"; else if (*accessed == "before") a << "-"; } a << bda; args.SetVar( "bda", a ); temp.Set(fRequest.GetDefaults()); temp << "&bda=" << a; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } } urlMaker.ConstructLocationURL( fNewURL, val, AC_BRANCHES, &args, fRequest.GetUnicode() ); if ( bFilterDefs ) fRequest.SetSaveFilterDefs(bFilterDefs); } break; case AC_CLIENTSPROCESSOR: { // // Parse a spec table to get the form's values // to determine how to filter spec.Add( "cnm" ); spec.Add( "cow" ); spec.Add( "cdu" ); spec.Add( "cda" ); spec.Add( "cho" ); spec.Add( "canuse" ); spec.Add( "Updated" ); spec.Add( "Accessed" ); char *val; if( fRequest.GetURL().Length() ) val = fRequest.GetURL().Text(); else val = NULL; // // If post data is missing return immediately. if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Parse the form elements to generate the url int bFilterDefs = fRequest.RmvDynArgBeginWith(fRequest.GetDefaults(), 'c'); if (!specTable.GetVar( "Clear" )) { StrBuf temp; int curUser = 0; const StrPtr *cow = specTable.GetVar( "cow" ); if ( cow && cow->Length() ) { if (!strcmp(cow->Text(), fRequest.GetUser().Text())) curUser = 1; else { args.SetVar( "cow", cow ); temp.Set(fRequest.GetDefaults()); temp << "&cow=" << cow; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } } const StrPtr *canuse = specTable.GetVar( "canuse" ); if ( canuse ) { StrBuf buf; buf << "2"; char *p = buf.Text(); if (curUser) *p |= 1; args.SetVar( "cfl", p ); temp.Set(fRequest.GetDefaults()); temp << "&cfl=" << p; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } else if (curUser) { args.SetVar( "cfl", "1" ); temp.Set(fRequest.GetDefaults()); temp << "&cfl=1"; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *cnm = specTable.GetVar( "cnm" ); if ( cnm && cnm->Length() ) { args.SetVar( "cnm", cnm ); temp.Set(fRequest.GetDefaults()); temp << "&cnm=" << cnm; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *cdu = specTable.GetVar( "cdu" ); if ( cdu && cdu->Length() && strcmp(cdu->Text(), "yyyy/mm/dd") ) { const StrPtr *updated = specTable.GetVar( "Updated" ); StrBuf u; if (updated) { if (*updated == "on") u << "_"; else if (*updated == "before") u << "-"; } u << cdu; args.SetVar( "cdu", u ); temp.Set(fRequest.GetDefaults()); temp << "&cdu=" << u; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *cda = specTable.GetVar( "cda" ); if ( cda && cda->Length() && strcmp(cda->Text(), "yyyy/mm/dd") ) { const StrPtr *accessed = specTable.GetVar( "Accessed" ); StrBuf a; if (accessed) { if (*accessed == "on") a << "_"; else if (*accessed == "before") a << "-"; } a << cda; args.SetVar( "cda", a ); temp.Set(fRequest.GetDefaults()); temp << "&cda=" << a; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *cho = specTable.GetVar( "cho" ); if ( cho && cho->Length() ) { StrBuf buf; buf << cho; char *p = buf.Text(); if (!strcmp(p, "\"\"")) { buf.Set("NULL"); p = buf.Text(); } args.SetVar( "cho", p ); temp.Set(fRequest.GetDefaults()); temp << "&cho=" << p; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } } urlMaker.ConstructLocationURL( fNewURL, val, AC_CLIENTS, &args, fRequest.GetUnicode() ); if ( bFilterDefs ) fRequest.SetSaveFilterDefs(bFilterDefs); } break; case AC_LABELSPROCESSOR: { // // Parse a spec table to get the form's values // to determine how to filter spec.Add( "AllC" ); spec.Add( "lfl" ); spec.Add( "lnm" ); spec.Add( "low" ); spec.Add( "ldu" ); spec.Add( "lda" ); spec.Add( "Updated" ); spec.Add( "Accessed" ); char *val; if( fRequest.GetURL().Length() ) val = fRequest.GetURL().Text(); else val = NULL; // // If post data is missing return immediately. if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Parse the form elements to generate the url int bFilterDefs = fRequest.RmvDynArgBeginWith(fRequest.GetDefaults(), 'l'); if (!specTable.GetVar( "Clear" )) { StrBuf temp; int curUser = 0; const StrPtr *low = specTable.GetVar( "low" ); if ( low && low->Length() ) { if (!strcmp(low->Text(), fRequest.GetUser().Text())) curUser = 1; else { args.SetVar( "low", low ); temp.Set(fRequest.GetDefaults()); temp << "&low=" << low; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } } const StrPtr *lfl = specTable.GetVar( "lfl" ); if ( lfl && lfl->Length() ) { StrBuf buf; buf << lfl; char *p = buf.Text(); if ( specTable.GetVar( "AllC" ) ) *p |= 2; else *p ^= 2; if (curUser) *p |= 1; if (*p & 0x0F) { args.SetVar( "lfl", buf ); temp.Set(fRequest.GetDefaults()); temp << "&lfl=" << lfl; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } } else if ( specTable.GetVar( "AllC" ) ) { if (curUser) { args.SetVar( "lfl", "3" ); temp.Set(fRequest.GetDefaults()); temp << "&lfl=3"; fRequest.SetDefaults(temp.Text()); } else { args.SetVar( "lfl", "2" ); temp.Set(fRequest.GetDefaults()); temp << "&lfl=2"; fRequest.SetDefaults(temp.Text()); } bFilterDefs = 1; } else if (curUser) { args.SetVar( "lfl", "1" ); temp.Set(fRequest.GetDefaults()); temp << "&lfl=1"; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *lnm = specTable.GetVar( "lnm" ); if ( lnm && lnm->Length() ) { args.SetVar( "lnm", lnm ); temp.Set(fRequest.GetDefaults()); temp << "&lnm=" << lnm; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *ldu = specTable.GetVar( "ldu" ); if ( ldu && ldu->Length() && strcmp(ldu->Text(), "yyyy/mm/dd") ) { const StrPtr *updated = specTable.GetVar( "Updated" ); StrBuf u; if (updated) { if (*updated == "on") u << "_"; else if (*updated == "before") u << "-"; } u << ldu; args.SetVar( "ldu", u ); temp.Set(fRequest.GetDefaults()); temp << "&ldu=" << u; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *lda = specTable.GetVar( "lda" ); if ( lda && lda->Length() && strcmp(lda->Text(), "yyyy/mm/dd") ) { const StrPtr *accessed = specTable.GetVar( "Accessed" ); StrBuf a; if (accessed) { if (*accessed == "on") a << "_"; else if (*accessed == "before") a << "-"; } a << lda; args.SetVar( "lda", a ); temp.Set(fRequest.GetDefaults()); temp << "&lda=" << a; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } if( specTable.GetVar( "AllC" ) ) urlMaker.ConstructLocationURL( fNewURL, val, AC_LABELSPATH, &args, fRequest.GetUnicode() ); else urlMaker.ConstructLocationURL( fNewURL, val, AC_LABELS, &args, fRequest.GetUnicode() ); } else { urlMaker.ConstructLocationURL( fNewURL, val, AC_LABELS, &args, fRequest.GetUnicode() ); } if ( bFilterDefs ) fRequest.SetSaveFilterDefs(bFilterDefs); } break; case AC_USERSPROCESSOR: { // // Parse a spec table to get the form's values // to determine how to filter spec.Add( "unm" ); spec.Add( "udu" ); spec.Add( "uda" ); spec.Add( "Updated" ); spec.Add( "Accessed" ); char *val; if( fRequest.GetURL().Length() ) val = fRequest.GetURL().Text(); else val = NULL; // // If post data is missing return immediately. if( !fRequest.ProcessForm( spec, &specTable ) ) { return 0; } // // Parse the form elements to generate the url int bFilterDefs = fRequest.RmvDynArgBeginWith(fRequest.GetDefaults(), 'u'); if (!specTable.GetVar( "Clear" )) { StrBuf temp; const StrPtr *unm = specTable.GetVar( "unm" ); if ( unm && unm->Length() ) { args.SetVar( "unm", unm ); temp.Set(fRequest.GetDefaults()); temp << "&unm=" << unm; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *udu = specTable.GetVar( "udu" ); if ( udu && udu->Length() && strcmp(udu->Text(), "yyyy/mm/dd") ) { const StrPtr *updated = specTable.GetVar( "Updated" ); StrBuf u; if (updated) { if (*updated == "on") u << "_"; else if (*updated == "before") u << "-"; } u << udu; args.SetVar( "udu", u ); temp.Set(fRequest.GetDefaults()); temp << "&udu=" << u; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } const StrPtr *uda = specTable.GetVar( "uda" ); if ( uda && uda->Length() && strcmp(uda->Text(), "yyyy/mm/dd") ) { const StrPtr *accessed = specTable.GetVar( "Accessed" ); StrBuf a; if (accessed) { if (*accessed == "on") a << "_"; else if (*accessed == "before") a << "-"; } a << uda; args.SetVar( "uda", a ); temp.Set(fRequest.GetDefaults()); temp << "&uda=" << a; fRequest.SetDefaults(temp.Text()); bFilterDefs = 1; } } urlMaker.ConstructLocationURL( fNewURL, val, AC_USERS, &args, fRequest.GetUnicode() ); if ( bFilterDefs ) fRequest.SetSaveFilterDefs(bFilterDefs); } break; case AC_P4CMDPROCESSOR: { char *postdata = fRequest.GetPostData(); if (!postdata) return 0; int tagged = strstr(postdata, "&tagged=tagged") ? 1 : 0; if (!tagged && strstr(postdata, "&tagged=xml")) tagged = 2; char *p = strstr(postdata, "&p4go"); if (p) *p = '\0'; *(postdata+2) = ' '; int i = 0; while ((p = strchr(postdata, '+')) != NULL) { *p = ' '; if (++i > 125) { fError = 1; ErrorMsg.Set( "Error: Maximum number of P4 command arguments is 125." ); return 0; } } if (!strncmp(postdata, "p4 p4 ", 5)) strcpy(postdata, postdata+3); while ((p = strchr(postdata, '%')) != NULL) { // Get the first nibble unsigned char i1 = *(p+1) - '0'; if (i1 > 9) i1 -= 7; i1 &= 0x0F; i1 *= 16; // Get the second nibble unsigned char i2 = *(p+2) - '0'; if (i2 > 9) i2 -= 7; i2 &= 0x0F; // add the nibbles to create the unescaped character *p = i1 + i2; // clear away the no longer needed escape digits strcpy(p+1, p+3); } StrBuf buf; if (strchr(postdata, '#') || strchr(postdata, '@')) { buf.Extend("", strlen(fRequest.GetPostData())*4); StrPtr ptr = buf; escapeHashAt(postdata, ptr); postdata = buf.Text(); } AllCommands newcmd; switch(tagged) { case 1: newcmd = AC_P4CMDTAGGED; break; case 2: newcmd = AC_P4CMDXML; break; default: newcmd = AC_P4CMD; break; } urlMaker.ConstructLocationURL( fNewURL, postdata, newcmd, &args, fRequest.GetUnicode() ); } break; case AC_GOPROCESSOR: { spec.Add( "type" ); spec.Add( "p4" ); if( !fRequest.ProcessForm( spec , &specTable ) ) return 0; const StrPtr *type = specTable.GetVar( "type" ); const StrPtr *p4 = specTable.GetVar( "p4" ); if (!type || !p4) return 0; switch(*(type->Text())) { case 'S': urlMaker.ConstructURL( fNewURL, p4->Text(), AC_DESCRIBE, NULL, fRequest.GetUnicode() ); fRequest.ReplaceBase( "rg", "s" ); break; case 'B': urlMaker.ConstructURL( fNewURL, p4->Text(), AC_BRANCHVIEW, NULL, fRequest.GetUnicode() ); fRequest.ReplaceBase( "rg", "b" ); break; case 'L': urlMaker.ConstructURL( fNewURL, p4->Text(), AC_LABELVIEW, NULL, fRequest.GetUnicode() ); fRequest.ReplaceBase( "rg", "l" ); break; case 'C': urlMaker.ConstructURL( fNewURL, p4->Text(), AC_CLIENTVIEW, NULL, fRequest.GetUnicode() ); fRequest.ReplaceBase( "rg", "c" ); break; case 'U': urlMaker.ConstructURL( fNewURL, p4->Text(), AC_USERVIEW, NULL, fRequest.GetUnicode() ); fRequest.ReplaceBase( "rg", "u" ); break; case 'J': urlMaker.ConstructURL( fNewURL, p4->Text(), AC_JOBVIEW, NULL, fRequest.GetUnicode() ); fRequest.ReplaceBase( "rg", "j" ); break; default: return 0; } } break; case AC_USERPSWD: { spec.Add( "u" ); spec.Add( "p" ); spec.Add( "c" ); spec.Add( "orgurl" ); if( !fRequest.ProcessForm( spec , &specTable ) ) return 0; const StrPtr *user = specTable.GetVar( "u" ); const StrPtr *pswd = specTable.GetVar( "p" ); const StrPtr *client = specTable.GetVar( "c" ); const StrPtr *orgurl = specTable.GetVar( "orgurl" ); if (!user || !user->Length()) return 0; fRequest.SetUser( user ); if (pswd) fRequest.SetPassword( pswd ); p4wLoginView loginView( fRequest ); loginView.Render(); if (loginView.fPasswordError) return 0; fRequest.SetSaveUserPswd(1); if (orgurl && orgurl->Length()) fNewURL.Set(orgurl); else { if (!client || !client->Length()) client = fRequest.GetStateArg( "cl" ); if (*(fRequest.GetDefaults().Text())) { StrBuf temp; temp.Alloc(fRequest.GetBase().Length() + fRequest.GetDefaults().Length()); char *t = temp.Text(); char *b; char *p = strchr(b = fRequest.GetBase().Text(), '@'); if (p) { strncpy(t, b, p-b); *(t + (p-b)) = '\0'; strcat(t, fRequest.GetDefaults().Text()); p = strchr(++p, '@'); if (p) { strcat(t, ++p); fRequest.SetBase(t); } } } urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); } if (client && client->Length()) { StrBuf temp; StrBuf sv; temp.Alloc(fRequest.GetBase().Length() + client->Length() + 8); char *t = temp.Text(); strcpy(t, fRequest.GetBase().Text()); char *p = strstr(t, "&cl="); char *q; if (p) { q = strchr(p+4, '&'); if (!q) q = strstr(t, "@/"); *p = '\0'; } else { q = strstr(t, "@/"); } if (q) { sv.Set(q); *q = '\0'; } else sv.Set("@//"); strcat(t, "&cl="); strcat(t, client->Text()); strcat(t, sv.Text()); temp.SetLength(); fRequest.SetBase(temp.Text()); } } break; default: { // // Parse "end-user" url. StrBuf fullPath; fullPath.Set( fRequest.GetPath().Text() ); char *p = fullPath.Text(); const char *ast = strchr( p, '*' ); const char *ellipse = strstr( p, "..." ); const char *at = strchr( p, '@' ); const char *hash = strchr( p, '#' ); // // don't treat * and ... as special for raw p4 commands if (fCommand == AC_P4CMD || fCommand == AC_P4CMDTAGGED || fCommand == AC_P4CMDXML) ast = ellipse = 0; const char *pathStart; StrBuf newBase; StrBuf newPath; if( ast != NULL || ellipse != NULL ) { // // Path browser with file matching. Find the beginning // of the pattern, and construct the new url. if( ellipse && ast ) { pathStart = ellipse < ast ? ellipse : ast; } else if( !ellipse ) { pathStart = ast; } else { pathStart = ellipse; } while( pathStart > p && *pathStart != '/' ) --pathStart; ++pathStart; // // Construct new base & pattern string. If "at" sign // found in pattern, pass it as the sr (symbolic rev) // argument. newBase.Set( p, pathStart - p ); // // If the url length is zero, the cd path // is corrupted. Replace it with a more reasonable // value. Also, remove the trailing slash from sr // and pat arguments. if( fRequest.GetURL().Length() == 0 ) { fRequest.ReplaceBase( "cd", newBase.Text() ); char *e = p + strlen( p ) - 1; *e = '\0'; } fRequest.ReplaceBase( "pat", pathStart ); fRequest.ReplaceBase( "path", newBase.Text() ); if( at ) args.SetVar( "sr", at + 1 ); urlMaker.ConstructLocationURL( fNewURL, NULL, AC_FILESMATCHING, &args, fRequest.GetUnicode() ); } else if( hash != NULL || at != NULL ) { // // Symbolic or numeric revisions in path. This will result in // either a path browser, file browser, or submitted changelist // request. StrBuf r1; StrBuf r2; const char *loc; const char *v1; const char *v2; char field; // // Hash: numeric revision. At sign: symbolic rev. If comma is // found, this will be a range of submitted changelists if( hash != NULL ) { loc = hash; field = '#'; v1 = "rev1"; v2 = "rev2"; } else { loc = at; field = '@'; v1 = "sr"; v2 = "sr2"; } const char *arg2 = strchr( loc, ',' ); if( !fRequest.GetURL().Length() ) { // // If url length is 0, we have an erroneous trailing // slash. The cd & 'path' path are corrupted, so fix // them and remove the trailing slash. char *e = p + strlen( p ) - 1; *e = '\0'; pathStart = loc; while( pathStart > p && *pathStart != '/' ) --pathStart; ++pathStart; newBase.Set( p, pathStart - p ); fRequest.ReplaceBase( "cd", newBase.Text() ); fRequest.ReplaceBase( "path", newBase.Text() ); } else { // // Get the start of the path node pathStart = urlMaker.GetNodeLocation( fullPath.Text(), 1, AC_PATHBROWSER ); } // // If the at or hash is not in the path node, this url // is hosed. Just pass as is to the file browser. if( !strchr( pathStart, field ) ) { urlMaker.ConstructLocationURL( fNewURL, fRequest.GetURL().Text(), AC_FILETEXTDEPOT, &args, fRequest.GetUnicode() ); return 1; } // // Set the revision or sr arg(s) if( arg2 ) { r1.Set( loc + 1, arg2 - loc - 1 ); if( *(arg2 + 1) == field ) arg2 += 2; else ++arg2; if( *arg2 ) r2.Set( arg2 ); } else { r1.Set( loc + 1 ); } newBase.Set( fullPath.Text(), pathStart - fullPath.Text() ); if( arg2 ) { args.SetVar( v1, r1 ); args.SetVar( v2, r2 ); fRequest.ReplaceBase( "path", newBase.Text() ); } if( *pathStart == field ) { // // Path is a directory. // If there are 2 args, this is a request for // a range of submitted changelists. Otherwise // this is a request for BITB if field is @. // If there is only one # argument for a directory, // ignore it. if( arg2 ) { urlMaker.ConstructLocationURL( fNewURL, NULL, AC_SUBMITTEDCHANGELISTS, &args, fRequest.GetUnicode() ); } else { if( field == '@' ) fRequest.ReplaceBase( "sr", pathStart + 1 ); fRequest.ReplaceBase( "path", newBase.Text() ); urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); } } else { // // Path is a file, not a directory. // When 2 args are specified, get the submitted // changes pane. Otherwise just get the mime-qualified text for // the specified (possibly symbolic) revision. const char *e = strchr( pathStart, field ); newPath.Set( pathStart, e - pathStart ); if ( arg2 ) { urlMaker.ConstructLocationURL( fNewURL, newPath.Text(), AC_SUBMITTEDCHANGELISTSFILE, &args, fRequest.GetUnicode() ); } else { fRequest.ReplaceBase( v1, e + 1 ); fRequest.ReplaceBase( "path", newBase.Text() ); urlMaker.ConstructLocationURL( fNewURL, newPath.Text(), AC_MIMECONTENT, &args, fRequest.GetUnicode() ); } } } else { // Handle P4 cmds separately if (fCommand == AC_P4CMD) return 0; // // check last character to determine whether this is a file or // path browser. If this is a file browser, return 0 so // that the caller will render the mime content as-is. char *e = fRequest.GetPath().Text() + fRequest.GetPath().Length() - 1; if( *e == '/' ) { AllCommands cmd = AC_PATHBROWSER; if (!strchr(fRequest.GetTabs().Text(), 'f')) { switch(*(fRequest.GetTabs().Text())) { case 'p': cmd = AC_PENDINGCHANGELISTS; break; case 's': cmd = AC_SUBMITTEDCHANGELISTS; args.SetVar( "mx", "50" ); break; case 'b': cmd = AC_BRANCHES; break; case 'l': cmd = AC_LABELS; break; case 'c': cmd = AC_CLIENTS; break; case 'u': cmd = AC_USERS; break; case 'j': cmd = AC_JOBS; args.SetVar( "mx", "25" ); break; default: cmd = AC_CONFIGURATION; break; } } urlMaker.ConstructLocationURL( fNewURL, NULL, cmd, &args, fRequest.GetUnicode() ); if (*(fRequest.GetDefaults().Text())) { StrBuf temp; temp.Alloc(fRequest.GetBase().Length() + fRequest.GetDefaults().Length()); char *t = temp.Text(); char *b; char *p = strchr(b = fRequest.GetBase().Text(), '@'); if (p) { strncpy(t, b, p-b); *(t + (p-b)) = '\0'; strcat(t, fRequest.GetDefaults().Text()); p = strchr(++p, '@'); if (p) { strcat(t, ++p); fRequest.SetBase(t); } } } } else return 0; } } break; } return 1; } void p4wRelocate::escapeHashAt(char *p, StrPtr ptr) { char str[2] = { 0, 0 }; StrBuf buf; int inName = 0; while (*p) { switch(*p) { case '/': if (*(p+1) == '/') inName = 1; str[0] = *p; buf << str; break; case ':': if (*(p+1) == '\\') inName = 1; str[0] = *p; buf << str; break; case '#': if (inName) { inName = 0; buf << ">"; } buf << "%2523"; break; case '@': if (inName) { inName = 0; buf << ">"; } buf << "%2540"; break; default: str[0] = *p; buf << str; break; } p++; } buf.StrCpy(ptr.Text()); } int p4wRelocate::sendPage() { // // Send new page using LOCATION directive to remap URL StrBuf location; if( fRequest.GetCmd() == AC_MENUPROCESSOR ) { fRequest.DoLocation( fNewURL.Text() ); return 1; } // // XXX MSIE needs the utf-8 characters escaped in // location urls if( fRequest.GetJavascriptMode() == 2 ) location << p4wStrBuf().NormalizeBase( fRequest.GetBase(), 0 ); else location << p4wStrBuf().NormalizeBase( fRequest.GetBase(), fRequest.GetUnicode() ); switch(fRequest.GetCmd()) { case AC_GOPROCESSOR: { char *p = strrchr(location.Text(), '@'); if (p) { *++p = '/'; *++p = '\0'; location.SetLength(); } } case AC_USERPSWD: if (*(location.Text() + location.Length() - 1) == '/' && *(location.Text() + location.Length() - 2) == '/') { *(location.Text() + location.Length() - 1) = '\0'; location.SetLength(); } break; } location << fNewURL; if (!fRequest.GetBrowseMode() && !SEC_ALLOW_ALL_CLIENTS && !fRequest.isLocalRequest() && strstr(location.Text(), "&cl=")) { p4wURL urlMaker; StrBufDict StateParms; StrBufDict DynParms; int len = fRequest.GetHTTPPort().Length() + sizeof("http://")-1 + fRequest.IsHTTPS(); StrPtr *url = new StrRef( location.Text() + len ); urlMaker.ParseURL( *url, &StateParms, &DynParms ); StrPtr *cl = StateParms.GetVar( "cl" ); delete url; if (cl && strcmp(cl->Text(), fRequest.GetClient().Text())) { char err = '\0'; p4wClientRootPane clientRootPane(*this, fRequest); const char *cliArgs[] = { "-o", cl->Text() }; fRequest.p4("client", 2, cliArgs, &clientRootPane); fRequest.p4Wait(); if (clientRootPane.IsInvalidClient()) { fError = 1; ErrorMsg << clientRootPane.GetErrorMsg(); if (strstr(ErrorMsg.Text(), " can only be used on host machine ")) err = '5'; else if (strstr(ErrorMsg.Text(), " only allowed to use a client whose root begins with ")) err = '6'; else err = '4'; } if (SEC_ALLOW_UNOWNED_CLIENTS && !clientRootPane.GetOwner().Length()) ; else if (strcmp(clientRootPane.GetOwner().Text(), fRequest.GetUser().Text())) { fError = 1; ErrorMsg.Set("Client "); ErrorMsg << cl->Text(); ErrorMsg << " may only be used by its owner."; err = '2'; } else if (!SEC_ALLOW_NOHOST_CLIENTS && !clientRootPane.GetHost().Length()) { fError = 1; ErrorMsg.Set("Clients whose host field is not specified can not be used."); err = '3'; } if (err) { char *p = strstr(location.Text(), "?ac="); if (!p) return 0; p += 4; *p = '\0'; location.SetLength(); location << AC_MULTIUSER << "&err="; location.Append(&err, 1); } } } fRequest.DoLocation( location.Text() ); return 1; } void p4wRelocate::remapBogusURL() { // // If this url is hopeless, relocate to file or path browser. StrBufDict args; p4wURL urlMaker; if( fRequest.GetURL().Length() ) urlMaker.ConstructLocationURL( fNewURL, fRequest.GetURL().Text(), AC_BROWSEFILE, &args, fRequest.GetUnicode() ); else urlMaker.ConstructLocationURL( fNewURL, NULL, AC_PATHBROWSER, &args, fRequest.GetUnicode() ); } void p4wRelocate::doWorkspaceCmd( AllCommands cmd, const char *path ) { // // Use the "Client root" field of the info command // for the workspace root value p4wWorkspacePane workspacePane( *this, fRequest ); fRequest.p4( "info", 0, 0, &workspacePane ); fRequest.p4Wait(); if( workspacePane.GetRoot() == NULL ) { fError = 1; } else { StrBuf wr; wr << workspacePane.GetRoot(); fRequest.ReplaceBase( "wr", wr.Text() ); fRequest.ReplaceBase( "cd", wr.Text() ); fRequest.ReplaceBase( "cdf", NULL ); if( cmd == AC_WORKSPACE || cmd == AC_GOTO ) { // // If the path has a leading /, insure it has an extra // leading / to terminate the state space. StrBuf newPath; if( *workspacePane.GetRoot() == '/' ) newPath << "/"; if( !path ) newPath << wr; else newPath << path; fRequest.ReplaceBase( "md", "w" ); fRequest.ReplaceBase( "path", newPath.Text() ); } } } void p4wRelocate::doPasswdCmd( const char *old, const char *newPasswd ) { // // Issue p4 passwd command and check for error p4wPasswdTestPane passwdPane( *this, fRequest ); if( old ) fOldPassword.Set( old ); if( newPasswd ) fNewPassword.Set( newPasswd ); fRequest.p4( "passwd", 0, 0, &passwdPane ); fRequest.p4Wait(); if( passwdPane.GotError() ) { fError = 1; ErrorMsg.Set( passwdPane.GetErrorMsg().Text() ); } else { fPasswordSet = 1; } } int p4wRelocate::DoAddDefaults() { // // Add the defaults, generate a location URL // and send a page with the location directive if( addDefs2URL() ) { if ( !sendPage() ) return 0; return 1; } return 0; } int p4wRelocate::addDefs2URL() { if (fRequest.GetCmd() == AC_USERPSWD) // don't add defaults to pswd dialog url return 0; StrBuf defs; defs << fRequest.GetDefaults(); if (*defs.Text() != '@') return 0; StrBuf base; base << fRequest.GetBase(); char *p = strchr(base.Text(), '@'); if (p) { *p = '\0'; base.SetLength(); } base << defs; p = strstr(base.Text(), "&D=1"); // &D=1 should never appear in a URL if (p) { strcpy(p, p+4); base.SetLength(); } fRequest.SetBase(base.Text()); fNewURL << fRequest.GetFullURL(); return 1; } int p4wRelocate::DoForceDefaults() { // // Force the defaults from the P4WDefaults cookie, // generate a location URL and if different from the // incoming URL, send a page with the location directive if( forceDefs2URL() ) { fRequest.DoLocation( fNewURL.Text() ); return 1; } return 0; } int p4wRelocate::forceDefs2URL() { StrBuf defs; defs << "/" << fRequest.GetDefaults(); if (*(defs.Text()+1) != '@') return 0; StrBuf savebase; savebase << fRequest.GetBase(); // we will need this if we decide not to redirect char *p = strstr(savebase.Text(), "&D=1"); // &D=1 should never appear in a URL if (p) { strcpy(p, p+4); savebase.SetLength(); fRequest.ReplaceBase( "D", NULL ); } // build a StrDict for the vars in the original URL p4wURL urlMaker; p = strstr(savebase.Text(), "/@"); if (!p) return 0; StrPtr *urlOrig = new StrRef( p ); StrBufDict stateOrigParms; StrBufDict dynOrigParms; urlMaker.ParseURL( *urlOrig, &stateOrigParms, &dynOrigParms ); // unset the existing state args in the URL int i; StrBuf rmList; // holds list of args to be cleared StrRef varref; StrRef valref; for (i=0; fRequest.GetStateArgX(i++, varref, valref); ) { if (!strcmp(varref.Text(), "md")) continue; if (!strcmp(varref.Text(), "cd")) continue; if (!strcmp(varref.Text(), "cdf")) continue; if (!strcmp(varref.Text(), "c")) continue; rmList << varref.Text() << "\t"; // add to list of args to clear } char *q; p = rmList.Text(); while ((q = strchr(p, '\t')) != NULL) // run thru list and doing clearings { *q = '\0'; fRequest.ReplaceBase( p, NULL ); p = ++q; } // build a StrDict for the vars in the defaults StrPtr *urlDefs = new StrRef( defs ); StrBufDict stateParms; StrBufDict dynParms; urlMaker.ParseURL( *urlDefs, &stateParms, &dynParms ); // set all the values in the defaults int b = 0; StrBuf temp; temp << defs; p = strchr(temp.Text(), '@'); while (p) { char *q = strchr(++p, '='); if (!q) break; *q++ = '\0'; if (strcmp(p, "md") && strcmp(p, "D")) { const StrPtr *oldval = stateOrigParms.GetVar( p ); const StrPtr *newval = stateParms.GetVar( p ); if (!oldval || strcmp(oldval->Text(), newval->Text())) b = 1; fRequest.ReplaceBase( p, newval->Text() ); } p = strchr(q, '&'); } // if nothing changed, don't redirect delete urlOrig; delete urlDefs; if (!b) { fRequest.SetBase(savebase.Text()); return 0; } fNewURL << fRequest.GetBase(); p = strchr(fNewURL.Text(), '@'); if (!p) { fRequest.SetBase(savebase.Text()); return 0; } p = strchr(p+1, '@'); if (!p) { fRequest.SetBase(savebase.Text()); return 0; } *p = '\0'; fNewURL.SetLength(); temp.Set(fRequest.GetFullURL()); p = strchr(temp.Text(), '@'); if (!p) { fRequest.SetBase(savebase.Text()); return 0; } p = strchr(p+1, '@'); if (!p) { fRequest.SetBase(savebase.Text()); return 0; } fNewURL << p; return 1; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 12234 | Matt Attaway |
Rejigger P4Web project in preparation for official sunsetting The bin directory contains the last official builds of P4Web from the Perforce download site. P4Web is soon to be completely sunsetted; these builds are here for folks who don't want to build their own. To better handle the archived builds the source code has been moved into a separate src directory. |
||
//guest/perforce_software/p4web/Views/p4wRelocate.cpp | |||||
#1 | 8914 | Matt Attaway | Initial add of the P4Web source code |