// // Copyright 2000 Perforce Software. All rights reserved. // // This file is part of Perforce - the FAST SCM System. // // p4wMimeContentView: // Renders output of print command using mime type determined by file suffix. // ------------------------------------- // Includes // #include <stdio.h> #include <string.h> #include <p4wp4.h> #include "p4wMimeContentView.h" #include "p4wMimeContentPane.h" #include "p4wWherePane.h" #include "p4wErrorView.h" p4wMimeContentView::p4wMimeContentView(p4wRequest & Request) : p4wView(Request) { } p4wMimeContentView::~p4wMimeContentView() { } // ------------------------------------- // Render this view. // void p4wMimeContentView::Render() { // // If this is a "Download File from Workspace" request, // call p4wMimeContentPane::RenderLocal() and return if (fRequest.GetCmd() == AC_DOWNLOADTOLOCAL) { StrBuf path; path.Set( fRequest.GetPath() ); if (fRequest.GetViewMode() != VM_WORKSPACE) { p4wWherePane wherePane(*this, fRequest); fRequest.p4Arg( path ); fRequest.p4( "where", 0, 0, &wherePane ); fRequest.p4Wait(); if (wherePane.fError) { Error e; p4wErrorView errorView( fRequest, wherePane.fErrMsg.Text(), 0 ); errorView.Render(); fRequest.p4Final(&e); return; } path.Set(wherePane.fLocalPath.Text()); } p4wMimeContentPane localPane( *this, fRequest ); localPane.RenderLocal( path.Text() ); return; } // // Request file text at head rev unless we have revision argument. const StrPtr *rev1 = fRequest.GetStateArg( "rev1" ); const StrPtr *rev1Dyn = fRequest.GetDynArg( "rev1" ); const StrPtr *revDyn = fRequest.GetDynArg( "rev" ); // alias for rev1 const StrPtr *srev = fRequest.GetDynArg( "sr" ); const StrPtr *srevState = fRequest.GetStateArg( "sr" ); // // If both dynamic & state parameters for sr are set, dynamic // wins...set srev to winner if( !srev && srevState ) srev = srevState; // // If both dynamic & state parameters for rev1 are set, state // wins...set rev1 to winner [wierd like this to not break old code] if( !rev1 && rev1Dyn ) rev1 = rev1Dyn; if( !rev1 && revDyn ) rev1 = revDyn; StrBuf path; path.Set( fRequest.GetPath() ); if( rev1 ) { path << "#" << rev1; } else if( srev ) { path << "@" << srev; } char *cmd; StrBuf errorMsg; Error e; p4wMimeContentPane printPane( *this, fRequest ); if ((fRequest.GetCmd() == AC_P4CMD || fRequest.GetCmd() == AC_P4CMDTAGGED || fRequest.GetCmd() == AC_P4CMDXML) && ((cmd = strstr(fRequest.GetFullURL().Text(), "/p4%20")) != NULL)) { if (SEC_DISALLOW_RAW_CMDS && !fRequest.isLocalRequest()) { errorMsg.Set("Raw P4 command input currently is not allowed."); p4wErrorView errorView( fRequest, errorMsg, 0, "securityflags" ); errorView.Render(); fRequest.p4Final(&e); return; } cmd += sizeof("/p4%20")-1; int inName = 0; int b = 0; int quot = 0; int argc = 0; char *argv[128]; char *p; p = cmd + strlen(cmd); while (*--p != '?') { if (p == cmd) break; } if (p != cmd) { *p = '\0'; p = cmd; } while (*p) { if (quot) { while (*p == '%' && *(p+1) == '2' && *(p+2) == '0') { *p = ' '; strcpy(p+1, p+3); p++; continue; } if (*p == '%' && *(p+1) == '2' && *(p+2) == '2') { *p = '\0'; p += 3; quot = 0; } } else { while (*p == '%' && *(p+1) == '2' && *(p+2) == '0') { *p = '\0'; p += 3; continue; } if (*p == '%' && *(p+1) == '2' && *(p+2) == '2') { p += 3; quot = 1; } } if (b) argv[argc++] = p; else b = 1; loop: while (*p == '%') { // 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); // decide what to do next if we are inside a filename if (inName) { if (*p == '>' || *p == '<') // these signal end of file name { strcpy(p, p+1); // thow < or > away; can't be in filename inName = 0; // indicate out of file name } else // don't loop back of names like break; // //depot/s/lookslikerev%239 will fail } } if (quot) { if (*p == '\"') { *p++ = '\0'; // end of this argv quot = 0; // end of quoted arg continue; // go back and do next one(s) } } else { if (*p == ' ') { *p++ = '\0'; // end of this argv continue; // go back and do next one(s) } } if (*p) // if just another char in argv { if (*p == '/' && *(p+1) == '/') inName = 1; else if (*p == ':' && *(p+1) == '\\') inName = 1; p++; goto loop; } } if (*cmd == '-') { errorMsg.Set("Error: You can not use global options with P4 commands within P4Web. See P4Web help for more information."); p4wErrorView errorView( fRequest, errorMsg, 0, "commands" ); errorView.Render(); fRequest.p4Final(&e); return; } if( fRequest.GetBrowseMode() && !CanBrowse(cmd) ) { errorMsg.Set("Operation not allowed in browse-only mode."); p4wErrorView errorView( fRequest, errorMsg, 0, "browseonly" ); errorView.Render(); fRequest.p4Final(&e); return; } if( !fRequest.GetBrowseMode() && !p4wAllCommands::AllowedInStandardMode(cmd) ) { errorMsg.Set("Operation not allowed in P4Web Standard or Viewer mode."); p4wErrorView errorView( fRequest, errorMsg, 0, "commands" ); errorView.Render(); fRequest.p4Final(&e); return; } if( SEC_DISALLOW_INTEG && !strcmp(cmd, "integ") && !fRequest.isLocalRequest() ) { errorMsg.Set("Integrations currently are not allowed."); p4wErrorView errorView( fRequest, errorMsg, 0, "browseonly" ); errorView.Render(); fRequest.p4Final(&e); return; } if( RequiresDashO(cmd) ) { b = 0; int n; for (n = argc; n--; ) { if (argv[n][0] == '-') { if (argv[n][1] == 'o' && !argv[n][2]) { b = 1; break; } if (argv[n][1] == 'd' && !argv[n][2]) { b = 2; break; } if (argv[n][1] == 'c' && !argv[n][2] && !strcmp(cmd, "submit")) { b = 3; break; } } } if (!b || ((b == 2) && fRequest.GetBrowseMode())) { StrBuf errorMsg; Error e; if (b == 2) errorMsg.Set("Operation not allowed in browse-only mode."); else if(!strcmp(cmd, "submit")) errorMsg.Set("Operation requires -c flag."); else errorMsg.Set("Operation requires -o flag."); p4wErrorView errorView( fRequest, errorMsg, 0, "commands" ); errorView.Render(); fRequest.p4Final(&e); return; } } b = 0; int ctr = -1; while (++ctr < argc) { if (strpbrk(argv[ctr], "|<>")) { StrBuf errorMsg; Error e; errorMsg.Set("Invalid command character - '<', '|' and '>' are not allowed."); p4wErrorView errorView( fRequest, errorMsg, 0, "commands" ); errorView.Render(); fRequest.p4Final(&e); return; } if (!strcmp(cmd, "print") && (strstr(argv[ctr], "...") || strchr(argv[ctr], '*') || strchr(argv[ctr], '?'))) { StrBuf errorMsg; Error e; errorMsg.Set("Wildcards are not allowed with "); errorMsg << cmd; p4wErrorView errorView( fRequest, errorMsg, 0, "commands" ); errorView.Render(); fRequest.p4Final(&e); return; } if (!fRequest.isLocalRequest()) { if (!strcmp(cmd, "reopen") && strstr(argv[ctr], "symlink") && !SEC_ALLOW_CR8CHG_SYMLINKS) { StrBuf errorMsg; Error e; errorMsg.Set("Permission denied to reopen a symlink file"); p4wErrorView errorView( fRequest, errorMsg, 0, "commands" ); errorView.Render(); fRequest.p4Final(&e); return; } if (argv[ctr][0] == '-') { if (argv[ctr][1] == 'o' && !argv[ctr][2]) b |= 1; if (argv[ctr][1] == 'i' && !argv[ctr][2]) b |= 2; } } } if (b == 3) // -> both -i and -o which is not allowed for remote users { StrBuf errorMsg; Error e; errorMsg.Set("The flags -o and -i cannot be used in the same command."); p4wErrorView errorView( fRequest, errorMsg, 0, "commands" ); errorView.Render(); fRequest.p4Final(&e); return; } fRequest.SetOutputInfoOK(1); printPane.SetP4Cmd(cmd); int i; for (i = 0; i < argc; ) printPane.AddP4CmdArg(argv[i++]); fRequest.p4(cmd, argc, (const char **)argv, &printPane); } else { // Hack for favicon.ico if (!strcmp(path.Text(), "//favicon.ico")) { Enviro enviro; char *p; if( !( p = enviro.Get( "P4WEBFAVICON" ) ) ) p = getenv( "P4WEBFAVICON" ); if ( ( p ) ) path.Set(p); else path.Set("//depot/favicon.ico"); } const char *printPaneArgs[] = { "-q", path.Text() }; fRequest.p4("print", 2, printPaneArgs, &printPane); } fRequest.p4Wait(); fRequest.SetOutputInfoOK(0); } int p4wMimeContentView::RequiresDashO(char *cmd) { switch(*cmd) { case 'b': if (!strcmp(cmd, "branch")) return 1; break; case 'c': if (!strcmp(cmd, "change")) return 1; if (!strcmp(cmd, "changelist")) return 1; if (!strcmp(cmd, "client")) return 1; break; case 'd': if (!strcmp(cmd, "depot")) return 1; break; case 'g': if (!strcmp(cmd, "group")) return 1; break; case 'j': if (!strcmp(cmd, "job")) return 1; if (!strcmp(cmd, "jobspec")) return 1; break; case 'l': if (!strcmp(cmd, "label")) return 1; break; case 'u': if (!strcmp(cmd, "user")) return 1; break; case 'w': if (!strcmp(cmd, "workspace")) return 1; break; case 's': if (!strcmp(cmd, "submit")) return 1; break; default: break; } return 0; } int p4wMimeContentView::CanBrowse(char *cmd) { switch(*cmd) { case 'a': if (!strcmp(cmd, "annotate")) return 1; break; case 'b': if (!strcmp(cmd, "branch")) return 1; if (!strcmp(cmd, "branches")) return 1; break; case 'c': if (!strcmp(cmd, "change")) return 1; if (!strcmp(cmd, "changes")) return 1; if (!strcmp(cmd, "changelist")) return 1; if (!strcmp(cmd, "changelists")) return 1; if (!strcmp(cmd, "client")) return 1; if (!strcmp(cmd, "clients")) return 1; break; case 'd': if (!strcmp(cmd, "describe")) return 1; if (!strcmp(cmd, "diff")) return 1; if (!strcmp(cmd, "diff2")) return 1; if (!strcmp(cmd, "depot")) return 1; if (!strcmp(cmd, "dirs")) return 1; break; case 'f': if (!strcmp(cmd, "filelog")) return 1; if (!strcmp(cmd, "files")) return 1; if (!strcmp(cmd, "fixes")) return 1; if (!strcmp(cmd, "fstat")) return 1; break; case 'h': if (!strcmp(cmd, "have")) return 1; if (!strcmp(cmd, "help")) return 1; case 'i': if (!strcmp(cmd, "info")) return 1; if (!strcmp(cmd, "integrated")) return 1; break; case 'j': if (!strcmp(cmd, "job")) return 1; if (!strcmp(cmd, "jobs")) return 1; break; case 'l': if (!strcmp(cmd, "label")) return 1; if (!strcmp(cmd, "labels")) return 1; break; case 'o': if (!strcmp(cmd, "opened")) return 1; break; case 'p': if (!strcmp(cmd, "print")) return 1; break; case 'r': if (!strcmp(cmd, "resolved")) return 1; break; case 'u': if (!strcmp(cmd, "user")) return 1; if (!strcmp(cmd, "users")) return 1; break; case 'w': if (!strcmp(cmd, "workspace")) return 1; if (!strcmp(cmd, "workspaces")) return 1; if (!strcmp(cmd, "where")) return 1; break; default: break; } return 0; } void p4wMimeContentView::RenderLocal() { StrBuf path; path.Set( fRequest.GetPath() ); p4wMimeContentPane localPane( *this, fRequest ); localPane.RenderLocal( path.Text() ); }
# | 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/p4wMimeContentView.cpp | |||||
#1 | 8914 | Matt Attaway | Initial add of the P4Web source code |