/* $Id: wsWebPage.cpp,v 1.10 2001/09/02 17:55:57 mike Exp $ *********************************************************************** * libwsmake - Core functionality library of wsmake * * Copyright (C) 1999,2000,2001 Michael Brownlow * * * * This program is free software; you can redistribute it and/or modify* * it under the terms of the GNU General Public License as published by* * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * * For questions and comments, please email the author at: * * mike@wsmake.org * ***********************************************************************/ #include #include #include #include "wsmake.h" #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_GLOB_H #include #endif #include "wsWebPage.h" #include "wsWebSite.h" #include "wsUtil.h" #include "wsmake.h" using namespace std; wsWebPage::wsWebPage (string config_dir, ifstream *config, wsPageGroup *pg) : wsPage(config_dir), sync_printed(0), clone(false), pagegroup(pg) { this->subtag_list = new wsSubTagList(); this->internal_subtag_list = new wsSubTagList(); this->subtaggroup_list = new wsSubTagGroupList(); this->pageorder_list = new wsPageOrderList(); this->theme_list = new wsThemeList(); this->clone_list = new wsPageList(); this->depend_list = new wsDependList(); this->setUpdate(false); this->setPageType("NORMAL"); this->setParseType("YES"); this->setStat(STATTYPE_NOCHANGE); this->setCommand(""); this->setOptions(""); if(!pagegroup->usingSourceTimestamp()) { wsDBObject::load(pagegroup->getDatabaseFilename().c_str(), pagegroup->getDatabaseFormat()); } this->load(config); if(!pagegroup->usingSourceTimestamp()) { this->setDatabaseKey(this->getDatabaseKey().c_str()); this->setValueType(DBA_DT_LONG); } DBGPRINT(("O:created: wsWebPage\n")); } wsWebPage::wsWebPage (string config_dir, wsPageGroup *pg) : wsPage(config_dir), sync_printed(0), clone(false), pagegroup(pg) { this->subtag_list = new wsSubTagList(); this->internal_subtag_list = new wsSubTagList(); this->subtaggroup_list = new wsSubTagGroupList(); this->pageorder_list = new wsPageOrderList(); this->theme_list = new wsThemeList(); this->clone_list = new wsPageList(); this->depend_list = new wsDependList(); this->setUpdate(false); this->setPageType("NORMAL"); this->setParseType("YES"); this->setStat(STATTYPE_NOCHANGE); this->setCommand(""); this->setOptions(""); if(!pagegroup->usingSourceTimestamp()) { wsDBObject::load(pagegroup->getDatabaseFilename().c_str(), pagegroup->getDatabaseFormat()); this->setValueType(DBA_DT_LONG); } DBGPRINT(("O:created: wsWebPage\n")); } wsWebPage::wsWebPage (string config_dir, ifstream *config, wsPageGroup *pg, wsWebPage *original) : wsPage(config_dir), sync_printed(0), clone(true), pagegroup(pg) { this->subtag_list = new wsSubTagList(); this->internal_subtag_list = new wsSubTagList(); this->subtaggroup_list = new wsSubTagGroupList(); this->pageorder_list = new wsPageOrderList(); this->theme_list = new wsThemeList(); this->clone_list = new wsPageList(); this->depend_list = new wsDependList(); this->setUpdate(false); this->setPageType("NORMAL"); this->setParseType("YES"); this->setStat(STATTYPE_NOCHANGE); this->setCommand(""); this->setOptions(""); original->copyTo(this); if(!pagegroup->usingSourceTimestamp()) { wsDBObject::load(pagegroup->getDatabaseFilename().c_str(), pagegroup->getDatabaseFormat()); } this->load(config); if(!pagegroup->usingSourceTimestamp()) { this->setDatabaseKey(this->getDatabaseKey().c_str()); this->setValueType(DBA_DT_LONG); } DBGPRINT(("O:created: wsWebPage clone\n")); } wsWebPage::~wsWebPage(void) { subtag_list->free(); internal_subtag_list->free(); depend_list->free(); delete subtag_list; delete internal_subtag_list; delete subtaggroup_list; delete pageorder_list; delete theme_list; delete clone_list; delete depend_list; DBGPRINT(("O:destroyed: wsWebPage\n")); } int wsWebPage::clean(void) { // If this default page is of type CGI, we have a header and footer file // to remove... if(this->getPageTypeID() == PAGETYPE_CGI) { __wsmake_print(1,"cleaning: `%s':`%s'...", this->getOutputPage().c_str(), cgi_header.c_str()); if(remove((this->getFullOutputPageDir()+"/"+cgi_header).c_str()) != 0) { __wsmake_print(1,"failed (%d)!\n", errno); } else { __wsmake_print(1,"done.\n"); } __wsmake_print(1,"cleaning: `%s':`%s'...", this->getOutputPage().c_str(), cgi_footer.c_str()); if(remove((this->getFullOutputPageDir()+"/"+cgi_footer).c_str()) != 0) { __wsmake_print(1,"failed (%d)!\n", errno); } else { __wsmake_print(1,"done.\n"); } } wsPage::clean(); return clone_list->clean(); } int wsWebPage::dump(ofstream *output) { wsPage::dump(output); return 0; } void wsWebPage::copyTo(wsWebPage *copy) { wsPage::copyTo(copy); *(copy->subtag_list) += subtag_list; *(copy->subtaggroup_list) += subtaggroup_list; *(copy->pageorder_list) += pageorder_list; *(copy->theme_list) += theme_list; copy->setPageType(getPageType()); copy->setParseType(getParseType()); copy->setCommand(getCommand()); copy->setOptions(getOptions()); DBGPRINT(("O: cloned `%s'\n", this->getOutputPage().c_str())); } int wsWebPage::pushBackSubTag(wsSubTag *subtag) { if(subtag == NULL) { return 0; } subtag_list->pushBackSubTag(subtag); return 1; } int wsWebPage::getDefaultPageTagID(const string *tag) { if(strcmp(tag->c_str(), "web_path") == 0) { __wsmake_print_error("web_path is deprecated; use web_page instead.\n"); return TAG_WEB_PAGE; } else if(strcmp(tag->c_str(), "web_page") == 0) return TAG_WEB_PAGE; else if(strcmp(tag->c_str(), "time_format") == 0) return TAG_TIME_FORMAT; else if(strcmp(tag->c_str(), "subtag_format") == 0) return TAG_SUBTAG_FORMAT; else if(strcmp(tag->c_str(), "source_page") == 0) return TAG_SOURCE_PAGE; else if(strcmp(tag->c_str(), "output_page") == 0) return TAG_OUTPUT_PAGE; else if(strcmp(tag->c_str(), "source_dir") == 0) return TAG_SOURCE_DIR; else if(strcmp(tag->c_str(), "output_dir") == 0) return TAG_OUTPUT_DIR; else if(strcmp(tag->c_str(), "Clone") == 0) return TAG_CLONE; else if(strcmp(tag->c_str(), "SubTag") == 0) return TAG_SUBTAG; else if(strcmp(tag->c_str(), "subtaggroup") == 0) return TAG_SUBTAGGROUP; else if(strcmp(tag->c_str(), "pageorder") == 0) return TAG_PAGEORDER; else if(strcmp(tag->c_str(), "theme") == 0) return TAG_THEME; else if(strcmp(tag->c_str(), "page_type") == 0) return TAG_PAGETYPE; else if(strcmp(tag->c_str(), "parse") == 0) return TAG_PARSE; else if(strcmp(tag->c_str(), "cgi_header") == 0) return TAG_CGIHEADER; else if(strcmp(tag->c_str(), "cgi_footer") == 0) return TAG_CGIFOOTER; else if(strcmp(tag->c_str(), "command") == 0) return TAG_COMMAND; else if(strcmp(tag->c_str(), "options") == 0) return TAG_OPTIONS; else if(strcmp(tag->c_str(), "depend") == 0) return TAG_DEPEND; return UNKNOWN; } int wsWebPage::getPageTypeID(void) const { if(strcmp(page_type.c_str(), "NORMAL") == 0) return PAGETYPE_NORMAL; else if(strcmp(page_type.c_str(),"CGI") == 0) return PAGETYPE_CGI; return UNKNOWN; } int wsWebPage::getParseID(const string *tag) { if(strcmp(tag->c_str(),"YES") == 0) return PARSE_YES; else if(strcmp(tag->c_str(),"NO") == 0) return PARSE_NO; else if(strcmp(tag->c_str(),"INCLUDES_ONLY") == 0) return PARSE_INCLUDES_ONLY; return UNKNOWN; } int wsWebPage::load(ifstream *config) { string buff; string tag; string value; bool done = false; int line = 0; #ifdef HAVE_GLOB_H int err; unsigned i; static glob_t matches; #endif // Set source and output directories to defaults if(!clone) { this->setSourceDir(pagegroup->getSourceDir()); this->setOutputDir(pagegroup->getOutputDir()); } while((!done) && (line=getNextConfigLine(config, &buff))!=0) { splitString(&tag, &value, &buff); if(tag.find("}") != string::npos) { done = true; } else { switch(this->getDefaultPageTagID(&tag)) { case TAG_SOURCE_PAGE : chopQuotes(&value); if(!clone) { this->setSourcePage(value); } break; case TAG_OUTPUT_PAGE : chopQuotes(&value); this->setName(value); // Set name so that targets work this->setOutputPage(value); break; case TAG_WEB_PAGE : chopQuotes(&value); this->setName(value); this->setOutputPage(value); if(!clone) { this->setSourcePage(value); } break; case TAG_SOURCE_DIR : chopQuotes(&value); this->setSourceDir(value); break; case TAG_OUTPUT_DIR : chopQuotes(&value); this->setOutputDir(value); break; case TAG_CLONE : clone_list->pushBackPage(new wsWebPage(this->getConfigDir(), config, pagegroup, this)); break; case TAG_SUBTAG : if(!subtag_list->pushBackSubTag(&value, pagegroup->getSubTagTagFront(), pagegroup->getSubTagTagBack(), this->getDatabaseKey(), pagegroup->getDatabaseFilename(), pagegroup->getDatabaseFormat())) { __wsmake_print_error("Error adding subtag `%s' (line %d)\n", value.c_str(),line); } break; case TAG_SUBTAGGROUP : chopQuotes(&value); if(!subtaggroup_list->pushBackSubTagGroup (pagegroup->findSubTagGroupWithName(value))) { __wsmake_print_error("Error adding subtaggroup `%s' (line %d)\n", value.c_str(),line); } break; case TAG_PAGEORDER : chopQuotes(&value); if(!pageorder_list->pushBackPageOrder (pagegroup->findPageOrderWithName(value))) { __wsmake_print_error("Error adding pageorder `%s' (line %d)\n", value.c_str(),line); } break; case TAG_THEME : chopQuotes(&value); if(!theme_list->pushBackTheme (pagegroup->findThemeWithName(value))) { __wsmake_print_error("Error adding theme `%s' (line %d)\n", value.c_str(),line); } else { this->setCommand(pagegroup->findThemeWithName(value)->getCommand()); this->setOptions(pagegroup->findThemeWithName(value)->getOptions()); } break; case TAG_DEPEND : chopQuotes(&value); if(value[0] != '/') { value.insert(0,"/"); value.insert(0, this->getFullSourcePageDir()); } #ifdef HAVE_GLOB_H if((err=glob(value.c_str(), GLOB_NOCHECK, NULL, &matches)) == 0) { for(i=0; i<(unsigned)matches.gl_pathc; i++) { value.assign(matches.gl_pathv[i]); if(!depend_list->pushBackDepend (wsDepend::findOrCreate(this->getFullSourcePageDir(), value, pagegroup))) { __wsmake_print_error("Error adding depend `%s' (line %d)\n", value.c_str(),line); } } } else { __wsmake_print_error("error with glob: %d (line %d)\n", err, line); } #endif break; case TAG_PAGETYPE : chopQuotes(&value); this->setPageType(value); break; case TAG_COMMAND : chopQuotes(&value); if(value[0] != '/') { value = this->getConfigDir() + "/" + value; } this->setCommand(value); break; case TAG_OPTIONS : chopQuotes(&value); this->setOptions(value); break; case TAG_PARSE : chopQuotes(&value); this->setParseType(value); break; case TAG_CGIHEADER : chopQuotes(&value); this->setCGIHeader(value); break; case TAG_CGIFOOTER : chopQuotes(&value); this->setCGIFooter(value); break; case TAG_TIME_FORMAT : chopQuotes(&value); pagegroup->setTimeFormat(value); break; case TAG_SUBTAG_FORMAT : chopQuotes(&value); pagegroup->setSubTagFormat(value); break; case UNKNOWN : default : __wsmake_print_error("unknown default page tag skipped " "(line %d): %s\n", line,tag.c_str()); return 0; break; } } } if(this->getSourcePage().length() == 0) { __wsmake_print_error("Either source_page or web_page must be set.\n"); return 0; } if(this->getOutputPage().length() == 0) { this->setOutputPage(getSourcePage()); } // Verify page types if(this->getPageTypeID() == PAGETYPE_CGI) { if(strcmp(cgi_header.c_str(),"") == 0) { __wsmake_print_error("warning: no CGI header file specified for %s, " "using header.html\n", this->getOutputPage().c_str()); this->setCGIHeader("header.html"); } if(strcmp(cgi_footer.c_str(),"") == 0) { __wsmake_print_error("warning: no CGI footer file specified for %s, " "using footer.html\n", this->getOutputPage().c_str()); this->setCGIFooter("footer.html"); } } // Set the command and options from the pagegroup if the command length is 0 // Note: this is after checking for theme commands/options during the load if(command.length() == 0) { this->setCommand(pagegroup->getCommand()); if(options.length() == 0) { this->setOptions(pagegroup->getOptions()); } else { this->setOptions(options); } } return 1; } int wsWebPage::setPageList(wsPageList *prepend, wsPageList *append) { DBGPRINT(("M: setting pagelists for page `%s'\n", this->getSourcePage().c_str())); pageorder_list->setPageList(prepend, append); theme_list->setPageList(prepend, append); return 1; } int wsWebPage::setInternalSubTagList(void) { static char tmptime[256]; DBGPRINT(("M: setting internal subtaglist for page `%s'\n", this->getSourcePage().c_str())); // Make sure this is a current run internal_subtag_list->free(); // Add in the internal subtags // Last modification time if(pagegroup->lastmod_tagname.length() != 0) { string time; time_t* tp = new time_t; *tp = getSourceLastMod(); strftime(tmptime, 256, pagegroup->getTimeFormat().c_str(), localtime(tp)); time.assign(tmptime); internal_subtag_list->pushBackSubTag (new wsSubTag(&pagegroup->lastmod_tagname,&time)); delete tp; } // wsmake Version if(pagegroup->wsmake_version_tagname.length() != 0) { internal_subtag_list->pushBackSubTag (new wsSubTag(&pagegroup->wsmake_version_tagname, new string(VERSION))); } // Output Path if(pagegroup->output_page_tagname.length() != 0) { internal_subtag_list->pushBackSubTag (new wsSubTag(&pagegroup->output_page_tagname, new string(this->getOutputPage()))); } // Full source path if(pagegroup->source_tagname.length() != 0) { internal_subtag_list->pushBackSubTag (new wsSubTag(&pagegroup->source_tagname, new string(this->getFullSourcePage()))); } // Full output path if(pagegroup->output_tagname.length() != 0) { internal_subtag_list->pushBackSubTag (new wsSubTag(&pagegroup->output_tagname, new string(this->getFullOutputPage()))); } // Header if(pagegroup->header_tagname.length() != 0) { internal_subtag_list->pushBackSubTag (new wsSubTag(&pagegroup->header_tagname, new string(this->getFullOutputPageDir()+"/"+cgi_header))); } // Footer if(pagegroup->footer_tagname.length() != 0) { internal_subtag_list->pushBackSubTag (new wsSubTag(&pagegroup->footer_tagname, new string(this->getFullOutputPageDir()+"/"+cgi_footer))); } return 1; } void wsWebPage::parseContent(ofstream *out) { recurse_level = 0; parseContentLoop(getFullSourcePage(),out); } void wsWebPage::parseContentLoop( string filename, ofstream *out) { string *line = new string(); char bline[MAXLINELEN]; int cnt; recurse_level++; ifstream source(filename.c_str(),ios::in); if(source) { if(getParseID(&parse_type) == PARSE_NO) { while((cnt = getNextBinaryLine(&source, bline)) != 0) { out->write(bline, cnt); } } else { if( (getParseID(&parse_type) == PARSE_YES) || ( (getParseID(&parse_type) == PARSE_INCLUDES_ONLY) && (recurse_level>1)) ) { while(getNextLine(&source,line)) { this->parseSubtags(line); this->parseIncludes(out, line); } } else { while(getNextLine(&source,line)) { this->parseIncludes(out, line); } } } if(recurse_level == 1) { __wsmake_print(1,"."); } else { if(recurse_level > 1) { __wsmake_print(1,"i"); } } } else { __wsmake_print(1,"X"); } recurse_level--; } void wsWebPage::parseSubtags(string *line) { bool done = false; // FIXME: We should optimize first, add all tags to a new // list and do recursive replacement in place. Then we // simply parse each line with one pass while(!done) { if( ! ((subtag_list->parse(line) == 1) || (subtaggroup_list->parse(line) == 1) || (theme_list->parse(line) == 1) || (internal_subtag_list->parse(line) == 1)) ) { done = true; } } } void wsWebPage::parseIncludes(ofstream *out, string *line) { string input; string start; string end; string runner1; string runner2; string result; int length, numincludes; unsigned pos1, pos2; #ifdef HAVE_GLOB_H int err; unsigned i; static glob_t matches; #endif numincludes = 0; /* PARSE_NO is tested in parseContentLoop now, may not need it here anymore */ if((this->getParseID(&parse_type) != PARSE_NO) && (pagegroup->validIncludeTag())) { input.assign(line->c_str()); runner2 = input; while((pos1 = runner2.find(pagegroup->include_tagfront.c_str())) < string::npos) { start = runner2.substr(pos1,runner2.length()); runner1.assign(start.substr(pagegroup->include_tagfront.length(), start.length())); pos2 = runner1.find(pagegroup->include_tagback); if(pos2 >= string::npos) { __wsmake_print(1,"X"); } else { *out << runner2.substr(0,pos1); end.assign(runner1.substr(pos2,runner1.length())); runner2.assign(end.substr(pagegroup->include_tagback.length(), end.length())); length = runner1.length()-end.length(); result.assign(runner1.substr(0,length)); if(result[0] != '/') { if(fileExists((this->getFullSourcePageDir() + "/" + result).c_str())) { result.insert(0, "/"); result.insert(0, this->getFullSourcePageDir()); } else if(fileExists((pagegroup->getIncludeDir() + "/" + result).c_str())) { result.insert(0, "/"); result.insert(0, pagegroup->getIncludeDir()); } else { /* Resort to the pages source dir; also used by globs */ result.insert(0, "/"); result.insert(0, this->getFullSourcePageDir()); } } #ifdef HAVE_GLOB_H if((err=glob(result.c_str(), GLOB_NOCHECK, NULL, &matches)) == 0) { for(i=0;i<(unsigned)matches.gl_pathc;i++) { result.assign(matches.gl_pathv[i]); this->parseContentLoop(result, out); numincludes++; } } else { __wsmake_print_error("error with glob: %d\n", err); } #else this->parseContentLoop(result, out); numincludes++; #endif } } if(numincludes != 0) { *out << end.substr(pagegroup->include_tagback.length(),end.length()); } else { *out << line->c_str(); } } else { *out << line->c_str(); } } // FIXME: redesign this function int wsWebPage::make() { int err, saveerrno; wsPageList *make_prepend_list = new wsPageList(); wsPageList *make_append_list = new wsPageList(); string output_filename; DBGPRINT(("M: making `%s'\n", this->getOutputPage().c_str())); // Run sync process again if(!update) { this->sync(0); } if(update) { if(!this->checkOutputDir()) return 0; if(!this->setPageList(make_prepend_list,make_append_list)) return 0; if(!this->setInternalSubTagList()) return 0; pagegroup->useTags(subtag_list, subtaggroup_list, theme_list, internal_subtag_list); // parse it if(this->getPageTypeID() == PAGETYPE_NORMAL) { // Print out sync info this->printSync(); __wsmake_print(1,"["); // If we are using a command, we first output wsmake's parsing // to a temporary file, then run the command on that if(this->getCommand().length() == 0) { output_filename.assign(this->getFullOutputPage()); } else { output_filename.assign(this->getFullSourcePage()+".wsm"); } ofstream output(output_filename.c_str(),ios::out); if(!output) { __wsmake_print_error("Error opening output file: %s\n", output_filename.c_str()); return 0; } else { if(!make_prepend_list->make(&output)) return 0; parseContent(&output); if(!make_append_list->make(&output)) return 0; } output.close(); __wsmake_print(1,"]\n"); // now do commands if we have them. with the /tmpnames for // input and the real output this time if(this->getCommand().length() != 0) { err=system((command + " " + this->getFormatOptions(output_filename)).c_str()); saveerrno = errno; if(err != 0) { __wsmake_print(1,"\n"); // Check errno first, if errno is not set, then this is error 127 // sent from the system call, not one by errno. If it is from errno, // it means /bin/sh could not be executed. if((err==127)&&(saveerrno == 127)) { __wsmake_print_error("/bin/sh could not be executed.\n"); } else { __wsmake_print_error("command errno = %d\n",errno); } return 0; } else { this->setDatabaseValue(this->getOutputLastMod()); } // Now delete the tmp file unlink(output_filename.c_str()); } } else { if(this->getPageTypeID() == PAGETYPE_CGI) { this->printSync(); __wsmake_print(1,"["); if(this->getCommand().length() == 0) { output_filename.assign(this->getFullOutputPageDir() + "/" + cgi_header); } else { output_filename.assign(this->getFullSourcePageDir() + "/" + cgi_header + ".wsm"); } ofstream header(output_filename.c_str(), ios::out); if(!header) { __wsmake_print_error("Error opening output file: %s\n", output_filename.c_str()); return 0; } else { if(!make_prepend_list->make(&header)) return 0; } header.close(); __wsmake_print(1,"]"); // now do commands if we have them. with the /tmpnames for // input and the real output this time if(this->getCommand().length() != 0) { err=system((command + " " + this->getFormatOptions(output_filename)).c_str()); saveerrno = errno; if(err != 0) { __wsmake_print(1,"\n"); // Check errno first, if errno is not set, then this is error 127 // sent from the system call, not one by errno. If it is from // errno, it means /bin/sh could not be executed. if((err==127)&&(saveerrno == 127)) { __wsmake_print_error("/bin/sh could not be executed.\n"); } else { __wsmake_print_error("command errno = %d\n",errno); } return 0; } // Now delete the tmp file unlink(output_filename.c_str()); } printSync(); __wsmake_print(1,"["); if(this->getCommand().length() == 0) { output_filename.assign(this->getFullOutputPage()); } else { output_filename.assign(this->getFullSourcePage()+".wsm"); } ofstream output(output_filename.c_str(),ios::out); if(!output) { __wsmake_print_error("Error opening output file: %s\n", output_filename.c_str()); return 0; } else { this->parseContent(&output); } output.close(); __wsmake_print(1,"]"); // now do commands if we have them. with the /tmpnames for // input and the real output this time if(this->getCommand().length() != 0) { err=system((command+" "+ this->getFormatOptions(output_filename)).c_str()); saveerrno = errno; if(err != 0) { __wsmake_print(1,"\n"); // Check errno first, if errno is not set, then this is error 127 // sent from the system call, not one by errno. If it is from // errno, it means /bin/sh could not be executed. if((err==127)&&(saveerrno == 127)) { __wsmake_print_error("/bin/sh could not be executed.\n"); } else { __wsmake_print_error("command errno = %d\n",errno); } return 0; } else { this->setDatabaseValue(this->getOutputLastMod()); } // Now delete the tmp file unlink(output_filename.c_str()); } this->printSync(); __wsmake_print(1,"["); if(this->getCommand().length() == 0) { output_filename.assign(this->getFullOutputPageDir()+"/"+cgi_footer); } else { output_filename.assign(this->getFullSourcePageDir()+"/"+ cgi_footer+".wsm"); } ofstream footer(output_filename.c_str(),ios::out); if(!footer) { __wsmake_print_error("Error opening output file: %s\n", output_filename.c_str()); return 0; } else { if(!make_append_list->make(&footer)) return 0; } footer.close(); __wsmake_print(1,"]\n"); // now do commands if we have them. with the /tmpnames for // input and the real output this time if(this->getCommand().length() != 0) { err=system((command+" "+ this->getFormatOptions(output_filename)).c_str()); saveerrno = errno; if(err != 0) { __wsmake_print(1,"\n"); // Check errno first, if errno is not set, then this is error 127 // sent from the system call, not one by errno. If it is from // errno, it means /bin/sh could not be executed. if((err==127)&&(saveerrno == 127)) { __wsmake_print_error("/bin/sh could not be executed.\n"); } else { __wsmake_print_error("command errno = %d\n",errno); } return 0; } // Now delete the tmp file unlink(output_filename.c_str()); } } else { __wsmake_print("error: %s : page type not recognized: `%s'\n", this->getOutputPage().c_str(), page_type.c_str()); } } this->setPermissions(); if(pagegroup->getTimes()) { this->setTime(); } if(!pagegroup->usingSourceTimestamp()) { this->setDatabaseValue(this->getOutputLastMod()); } // __wsmake_print(1,"]\n"); } else { if(((__wsmake_get_level() == 1)&&(this->getStat() != STATTYPE_NOCHANGE))|| ((__wsmake_get_level() >= 2)&&(this->getStat() == STATTYPE_NOCHANGE))) { this->printSync(); __wsmake_print(1,"\n"); } } delete make_prepend_list; delete make_append_list; depend_list->make(); return clone_list->make(); } int wsWebPage::make(ofstream *output) { *output << "Not implemented.\n"; return 0; } string wsWebPage::getFormatOptions(string input_filename) const { string formatoptions(options); string source("%s"); string output("%o"); string sourcedir("%ds"); string outputdir("%do"); string input("%i"); string webpath("%w"); if(input_filename == this->getFullOutputPage()) { __wsmake_print_error("Uh oh. Input and output are the same. `%s'\n" "That's not supposed to happen, so i'll quit now.\n" "if you think this is a bug, send your configuration " "file to bugs@wsmake.org.\nThanks!\n", input_filename.c_str()); assert(0); } // Parse format specifiers: // %sd searchAndReplace(&formatoptions, sourcedir, this->getFullSourceDir()); // %od searchAndReplace(&formatoptions, outputdir, this->getFullOutputDir()); // %i searchAndReplace(&formatoptions, input, input_filename); // %s searchAndReplace(&formatoptions, source, this->getFullSourcePage()); // %o searchAndReplace(&formatoptions, output, this->getFullOutputPage()); // %w searchAndReplace(&formatoptions, webpath, this->getOutputPage()); return formatoptions; } void wsWebPage::print(void) const { __wsmake_print(3,"Webpage\n"); __wsmake_print(3,"===================\n"); wsPage::print(); __wsmake_print(3," Parse Type : %s\n", parse_type.c_str()); __wsmake_print(3," Page Type : %s\n", page_type.c_str()); __wsmake_print(3," CGI Header : %s\n", cgi_header.c_str()); __wsmake_print(3," CGI Footer : %s\n", cgi_footer.c_str()); if(__wsmake_get_level() >= 3) { __wsmake_print(3," Subtags : "); subtag_list->print(); __wsmake_print(3,"\n"); __wsmake_print(3," Subtag Groups : "); subtaggroup_list->printNames(); __wsmake_print(3,"\n"); __wsmake_print(3," Pageorders : "); pageorder_list->printNames(); __wsmake_print(3,"\n"); } __wsmake_print(3,"===================\n"); } void wsWebPage::printSync(void) { if(!sync_printed) { if((__wsmake_get_level()>=2)||(getStat() != STATTYPE_NOCHANGE)) { pagegroup->printStatType(this->getStat()); if(!clone) { __wsmake_print(1,"Webpage: %-30s", this->getOutputPage().c_str()); } else { __wsmake_print(1,"Clone : %-30s", this->getOutputPage().c_str()); } } sync_printed = 1; } } int wsWebPage::sync(int force) { sync_printed = 0; long lastmod = 0; bool using_timestamp = pagegroup->usingSourceTimestamp(); if(using_timestamp || ready()) { DBGPRINT(("S: syncing webpage `%s'\n", this->getOutputPage().c_str())); if(!using_timestamp) { // Sync nested objects first (non-referenced attributes) subtag_list->sync(force); depend_list->sync(force); } // Does the source page exist? if(!clone) { if(!this->sourcePageExists()) { DBGPRINT(("S: discard `%s' (no source page)\n", this->getOutputPage().c_str())); this->setStat(STATTYPE_NOSOURCEPAGE); return 0; } } if(!using_timestamp) { // Check if page is in database if(!this->dbKeyExists(this->getDatabaseKey().c_str())) { DBGPRINT(("S: update `%s' (no key)\n", this->getOutputPage().c_str())); // We set this to 0 now so that if the first "make" fails, it will // continue to try and make. // pagegroup->dbAdd(getDatabaseKey(),0); this->setDatabaseKey(getDatabaseKey().c_str()); this->setDatabaseValue(0l); this->setUpdate(true); this->setStat(STATTYPE_NEWPAGE); return clone_list->sync(force); } // Get lastmod now that we know a record exists for this page if(this->getDatabaseValue(&lastmod)==NULL) { __wsmake_print_error("key value could not be found! (`%s')\n", this->getOutputPage().c_str()); return 0; } } else { } // Did they say to force an update? if(force) { DBGPRINT(("S: update `%s' (forced)\n", this->getOutputPage().c_str())); this->setStat(STATTYPE_FORCE); this->setUpdate(true); return clone_list->sync(force); } // Is the source file modified? if(!clone && !using_timestamp) { if(lastmod < this->getSourceLastMod()) { DBGPRINT(("S: update `%s' (source file updated) %ld < %ld\n", this->getOutputPage().c_str(), lastmod, this->getSourceLastMod())); this->setStat(STATTYPE_SOURCEUPDATED); this->setUpdate(true); return clone_list->sync(1); } } // Does the output file exist? if(!this->outputPageExists()) { DBGPRINT(("S: update `%s' (no output page)\n", this->getOutputPage().c_str())); this->setStat(STATTYPE_NOOUTPUTPAGE); this->setUpdate(true); return clone_list->sync(force); } // Is the output file old? if(using_timestamp) { if(this->getOutputLastMod() < this->getSourceLastMod()) { DBGPRINT(("S: update `%s' (source file updated) %ld < %ld\n", this->getOutputPage().c_str(), this->getOutputLastMod(), this->getSourceLastMod())); this->setStat(STATTYPE_SOURCEUPDATED); this->setUpdate(true); return clone_list->sync(force); } } else { if(this->getOutputLastMod() < lastmod) { DBGPRINT(("S: update `%s' (output page is old) %ld > %ld\n", this->getOutputPage().c_str(), lastmod, this->getSourceLastMod())); this->setStat(STATTYPE_OLDOUTPUTPAGE); this->setUpdate(true); return clone_list->sync(force); } // Were any subtags updated? if(subtag_list->isUpdated()) { DBGPRINT(("S: update `%s' (subtag updated)\n", this->getOutputPage().c_str())); this->setStat(STATTYPE_SUBTAGUPDATED); this->setUpdate(true); return clone_list->sync(force); } // Were any pageorders updated? if(pageorder_list->isUpdated()) { DBGPRINT(("S: update `%s' (pageorder updated)\n", this->getOutputPage().c_str())); this->setStat(STATTYPE_PAGEORDERUPDATED); this->setUpdate(true); return clone_list->sync(force); } // Were any subtaggroups updated? if(subtaggroup_list->isUpdated()) { DBGPRINT(("S: update `%s' (subtaggroup updated)\n", this->getOutputPage().c_str())); this->setStat(STATTYPE_SUBTAGGROUPUPDATED); this->setUpdate(true); return clone_list->sync(force); } // Were any themes updated? if(theme_list->isUpdated()) { DBGPRINT(("S: update `%s' (theme updated)\n", this->getOutputPage().c_str())); this->setStat(STATTYPE_THEMEUPDATED); this->setUpdate(true); return clone_list->sync(force); } // Was a dependency updated? if(depend_list->isUpdated()) { DBGPRINT(("S: update (dependency updated)\n")); this->setStat(STATTYPE_DEPENDUPDATED); this->setUpdate(true); return clone_list->sync(force); } } } else { __wsmake_print_error("database isn't ready\n"); this->setStat(STATTYPE_ERROR); this->setUpdate(false); return 0; } return 0; }