// // Copyright 2001 Perforce Software. All rights reserved. // // This file is part of Perforce - the FAST SCM System. // // p4wRSSJobsPane: // List of jobs with a form to change filter and/or // max number of jobs to display #include <stdio.h> #include <string.h> #include <p4wp4.h> #include "p4wStrBuf.h" #include "p4wPane.h" #include "p4wRSSJobsPane.h" #include "p4wRSSJobsView.h" extern Ident ident; p4wRSSJobsPane::p4wRSSJobsPane( p4wView & ParentView, p4wRequest & Request ) : p4wPane( ParentView, Request ), fSeenBegin(0), fGotSpec(0), fSeenData(0) { } p4wRSSJobsPane::~p4wRSSJobsPane() { } void p4wRSSJobsPane::Begin() { const StrPtr *mx = fRequest.GetDynArg( "mx" ); const StrPtr *ft = fRequest.GetDynArg( "ft" ); const StrPtr *jasc = fRequest.GetDynArg( "jasc" ); const StrPtr *jfp = fRequest.GetDynArg( "jfp" ); const StrPtr *jin = fRequest.GetDynArg( "jin" ); StrPtr fMX; StrPtr fFT; if (!mx) { fMX = GetDefaultMX(); mx = &fMX; if (!mx->Length()) mx = 0; } if (!ft) { fFT = GetDefaultFT(); ft = &fFT; if (!ft->Length()) ft = 0; } if (feedTitle.Length() == 0) { feedTitle << "Jobs - "; if (ft) feedTitle << "(" << ft->Text() << ") - "; if ( mx ) feedTitle << "Last " << mx->Text(); else feedTitle << "All"; } p4wHtml htm; const char *charset = NULL; if( fRequest.GetUnicode() ) charset = "utf-8"; htm.httpHeader( 200 ); htm.serverId(); htm.contentType( "application/rss+xml", 1, charset ); fRequest << htm; StrBuf feedDesc; feedDesc << "Perforce Jobs"; fRequest << "<?xml version=\"1.0\" encoding=\""; fRequest << (fRequest.GetUnicode() ? "UTF-8" : "ISO-8859-1") << "\"?>\n"; fRequest << "<rss version=\"2.0\">\n"; fRequest << " <channel>\n"; fRequest << " <title>"; fRequest << p4wStrBuf().EscapeHTMLDoURLs(feedTitle).Text() << "</title>\n"; StrBuf jobURL; p4wURL urlMaker; p4wStrBuf jobURLFormatted; StrBuf newBase; fRequest.UseNewBaseDoCache( newBase, NULL, "cd", "//" ); fRequest.UseNewBaseDoCache( newBase, newBase.Text(), "md", "c" ); StrBufDict args; if (mx) args.SetVar( "mx", mx->Text() ); if (ft) args.SetVar( "ft", ft->Text() ); if (jasc) args.SetVar( "jasc", jasc->Text() ); if (jfp) args.SetVar( "jfp", jfp->Text() ); if (jin) args.SetVar( "jin", jin->Text() ); urlMaker.ConstructURL( jobURL, newBase.Text(), AC_JOBS, &args ); int i; StrPtr *s; for( i = 0; ( s = (StrPtr *)fRequest.GetDynArg( "jsf", i ) ) != NULL; i++ ) jobURL << "&jsf=" << s; if (fRequest.IsHTTPS()) jobURLFormatted << "https://"; else jobURLFormatted << "http://"; jobURLFormatted << fRequest.GetHTTPPort().Text(); jobURLFormatted.EscapeHTML(jobURL); fRequest << " <link>" << jobURLFormatted.Text() << "</link>\n"; fRequest << " <description>" << feedDesc << "</description>\n"; fRequest << " <generator>" << "P4Web" "/" ID_OS "/" ID_REL "/" ID_PATCH " (" ID_Y "/" ID_M "/" ID_D ")" << "</generator>\n"; } void p4wRSSJobsPane::Render( StrDict * varList ) { // // The first row of data contains the spec definition // with the field names. fSeenData = 1; SpecElem *se; StrPtr *specString = varList->GetVar( StrRef("specdef") ); if( specString != NULL ) { Error e; fJobSpec.Decode( specString, &e ); ++fGotSpec; } // // Decide if we can output this job. If the page is // too big or the spec definition is missing we have // to bail out. if( PageLimitExceeded() || !fGotSpec ) return; // // Generate the XML for each job p4wURL urlMaker; int nCols; StrBuf jobName; StrBuf jobUser; StrBuf jobDate; p4wStrBuf title; int j; if( !fSeenBegin) { fSeenBegin = 1; for( j = 0; j < fJobSpec.Count(); j++ ) { se = fJobSpec.Get( j ); StrPtr *value = varList->GetVar( se->tag ); if (se->code == 104) { const char *field = value->Text(); jobDate.Set( field ); char time_buffer[255 + 1]; // Do our own strftime time_buffer[0] = '\0'; DateTime t; Error e; t.Set( jobDate.Text(), &e ); time_t iTime = (time_t) t.Value(); StrBuf time_format; time_format.Append( "%a, %d %b %Y %H:%M:%S" ); strftime( time_buffer, sizeof( time_buffer ), time_format.Text(), gmtime( &iTime ) ); fRequest << " <lastBuildDate>" << time_buffer << " GMT</lastBuildDate>\n"; break; } } } // // Generate the job entry fRequest << " <item>\n"; StrBuf jobURL; StrBuf newBase; fRequest.UseNewBase( newBase, NULL, "path", NULL ); const StrPtr *pcl = fRequest.GetDynArg( "pcl" ); const StrPtr *sr = fRequest.GetDynArg( "sr" ); // // First loop thru the fields and get the values needed from 101 - 105 for( j = 0; j < fJobSpec.Count(); j++ ) { se = fJobSpec.Get( j ); StrPtr *value = varList->GetVar( se->tag ); if( !value ) { continue; } const char *field = value->Text(); switch ( se->code ) { case 101: { int len = strlen( field ); if( *field == '"' && ( *( field + len - 1 ) == '"' ) ) jobName.Set( field + 1, len - 2 ); else jobName.Set( field ); break; } case 103: jobUser.Set( field ); break; case 104: jobDate.Set( field ); break; case 105: title.Set( field ); break; } } if (title.Length() > 40) { char *p = title.Text() + 40; *p = '\0'; while (*--p <= ' ' && p > title.Text()) *p = '\0'; title.SetLength(); } fRequest << " <title>Job: " << jobName << ": "; fRequest << p4wStrBuf().EscapeHTMLDoURLs(title).Text() << "</title>\n"; fRequest.ReplaceBase( "pgc", "y" ); fRequest.UseNewBase( newBase, NULL, "path", NULL ); newBase << jobName; urlMaker.ConstructURL( jobURL, newBase.Text(), AC_JOBVIEW, NULL, fRequest.GetUnicode() ); p4wStrBuf jobURLFormatted; if (fRequest.IsHTTPS()) jobURLFormatted << "https://"; else jobURLFormatted << "http://"; jobURLFormatted << fRequest.GetHTTPPort().Text(); jobURLFormatted.EscapeHTML(jobURL); char time_buffer[255 + 1]; // Do our own strftime time_buffer[0] = '\0'; DateTime t; Error e; t.Set( jobDate.Text(), &e ); time_t iTime = (time_t) t.Value(); StrBuf time_format; time_format.Append( "%a, %d %b %Y %H:%M:%S" ); strftime( time_buffer, sizeof( time_buffer ), time_format.Text(), gmtime( &iTime ) ); fRequest << " <pubDate>" << time_buffer << " GMT</pubDate>\n"; fRequest << " <link>" << jobURLFormatted.Text() << "</link>\n"; char * p4webrssauthor = getenv( "P4WEBRSSAUTHOR" ); if ( p4webrssauthor ) fRequest << " <author>" << p4webrssauthor << "</author>\n"; else fRequest << " <author>" << jobUser << "@" << jobUser << ".eml</author>\n"; fRequest << " <description>"; // // Now loop thru again and build the output p4wHtml htm( 1 ); for( j = 0; j < fJobSpec.Count(); j++ ) { // // Skip hidden fields se = fJobSpec.Get( j ); if( isHiddenField( se->tag.Text(), se->code ) ) continue; StrPtr *value = varList->GetVar( se->tag ); if( !value ) { continue; } const char *field = value->Text(); StrBuf tagbuf; tagbuf << fJobSpec.Get( j )->tag.Text() << ": "; if( se->code == 101 ) { continue; } else if( se->IsDate() ) { // // Truncate the min:sec from any date // fields if found const char *end = strchr( field, ' ' ); if( !end ) end = strchr( field, '\0' ); StrRef Date( field, end - field ); htm.text( tagbuf.Text(), "b"); htm << Date.Text() << "\n"; } else if( se->IsText() ) { // // Truncate text fields to a fixed length int mLen = 1250; StrBuf tField; if( value->Length() > mLen ) { char *s = value->Text(); // // Make sure we break on a legal character // if this is a unicode installation if( GlobalCharSet::Get() != 0 ) { char *p = s + value->Length(); int i = 0; CharStep *ss = CharStep::Create( s, GlobalCharSet::Get() ); while( ( ss->Next() < p ) && ( ++i < mLen ) ); mLen = ss->Ptr() - s; delete ss; } tField.Set( s, mLen ); } else { tField.Set( field ); } htm.text( tagbuf.Text(), "b"); htm.beginBlockquote(); htm.beginUnformatted(); htm << p4wStrBuf().EscapeHTMLDoURLs(tField).Text() << "\n"; htm.endUnformatted(); htm.endBlockquote(); } else { htm.text( tagbuf.Text(), "b"); htm << field << "\n"; } htm.linebreak(); p4wStrBuf buf; buf.EscapeHTML(htm); fRequest << buf; htm.Clear(); buf.Clear(); } fRequest << " </description>\n"; fRequest << " </item>\n"; } void p4wRSSJobsPane::End() { fRequest << " </channel>\n"; fRequest << "</rss>\n"; } int p4wRSSJobsPane::isHiddenField( const char *field, int code ) { // // Return true if the field should be hidden. int hf = 1; const StrPtr *p; int i; // // Check dynamic argument (job show field) to see if // this field was selected to be shown. for( i = 0; ( p = fRequest.GetDynArg( "jsf", i ) ) != NULL; i++ ) { if( *p == field ) { --hf; break; } } // // If there are no dynamic jsf variables, only the first // 5 job fields are shown by default. if( hf && !i ) hf = code > 105; return hf; }
# | 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/Panes/p4wRSSJobsPane.cpp | |||||
#1 | 8914 | Matt Attaway | Initial add of the P4Web source code |