// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // Copyright 1999 Jose M. Vidal // Jose M. Vidal, vidal@multiagent.com, http://jmvidal.ece.sc.edu // // This program is free software. You can redistribute it and/or modify // it under the terms of the GNU General Public License // // // $Id: element.C,v 1.22 2002/04/02 19:02:22 jmvidal Exp $ #ifdef HAVE_CONFIG_H #include #endif #include "element.H" #include "iwebstream.H" extern string trim(const string & s); extern int replaceAll(string & s, string s1, string s2); extern string myItoa (int n); //Creates a new element using the first definition it finds in fileContents // If none, it creates an element of type="" //Eliminates this definition from fileContents. element::element(string & fileContents, int idnum) : type(""), printTemplate(""), separator(""), top(""), bottom(""), between(""), daysOld(0), numCols(1), maxNum(0), startNum(0) { string key = PLACEHOLDER + ":" + BEGIN_TAG; string::size_type blockStart = fileContents.find(key); if (blockStart == string::npos) return; //no more elements there; string::size_type endKey= fileContents.find(" ", blockStart); string::size_type endDef= fileContents.find(PLACEHOLDEREND, blockStart); type = fileContents.substr(endKey, endDef - endKey); type = trim(type); cout << "Found " << type << " block." << endl; string endKeyString = PLACEHOLDER + ":" + END_TAG + PLACEHOLDEREND; string::size_type blockEnd = fileContents.find(endKeyString, blockStart); //Make a copy of the block and search it for all the variables and values. //Set the data member values using them. key = PLACEHOLDER + ":"; string block = fileContents.substr(endDef, blockEnd - endDef); string::size_type start =0; string::size_type endName= 0; while ((start = block.find(key)) != string::npos) { endName = block.find(" ", start); string varName = block.substr(start + key.size(), endName -( start + key.size())); // cout << "varName=" << varName << endl; endDef = block.find(PLACEHOLDEREND, endName); string varValue = block.substr(endName, endDef - endName); // cout << "varValue=" << varValue << endl; trim(varValue); if (varName == COLS_VAR) numCols = atoi(varValue.c_str()); else if (varName == TEMPLATE_VAR) printTemplate = varValue; else if (varName == TOP_VAR) top = varValue; else if (varName == BOTTOM_VAR) bottom = varValue; else if (varName == BETWEEN_VAR) between = varValue; else if (varName == SEPARATOR_VAR) separator = varValue; else if (varName == MAXNUM_VAR) maxNum = atoi(varValue.c_str()); else if (varName == STARTNUM_VAR) startNum = atoi(varValue.c_str()); else if (varName == DAYSOLD_VAR) daysOld = atoi(varValue.c_str()); else cerr << "Did not understand " << key << varName << endl; block.replace(start, endDef + PLACEHOLDEREND.size() - start, ""); } //Eliminate the block and put a marker in its place fileContents.replace(blockStart, blockEnd + endKeyString.size() - blockStart, PLACEHOLDER + ":" + myItoa(idnum) + PLACEHOLDEREND); } /**Append the list of refs into ouput using our variable values to guide the output. Does not output reference r if r.isPrivate(); If type == folder then only output if r.isFolder() otherwise only output if !(r.isFolder()) */ string element::sendAsHTML(vector & refs, const string varValues []){ string output = ""; int count = 0; int total =0; int skipped = 0; // cout << "sendAsHtml refs.size()=" << refs.size() << "maxNum=" << maxNum << " type=" << type << endl; if (maxNum == 0) maxNum = 9999; time_t currentTime = time(0); //.tv_sec; time_t timeCutoff = currentTime - (daysOld * 60 * 60 * 24); if (daysOld == 0) timeCutoff = -1; for (vector::iterator i = refs.begin(); i != refs.end(); ++i){ //calculate the total we will print out reference &r = *i; if ( !(r.isPrivate()) && (r.creationTime > timeCutoff) && (((type == FOLDER_TYPE) && (r.isFolder())) || ((type != FOLDER_TYPE) && !(r.isFolder())))) { if (++skipped < startNum) continue; total++; if (++count >= maxNum) //enough in this. break; } } // cout << "Total leafs = " << total << " type=" << type << endl; if (total == 0) return output; //no need to waste time //sort refs if they need it (depends on the type) if ((type == NEWADD_TYPE) || (type == NEWS_TYPE) || (type == NEWSANDNEWADD_TYPE)){ sort(refs.begin(), refs.end(), referenceCmpCreation()); //sort based on add date // cout << refs[0] << endl << refs[1] << endl; } else if (type == TOPHITS_TYPE){ sort(refs.begin(), refs.end(), referenceCmpHits()); //sort based on hits }; output += top; count = 0; skipped = 0; int numPerRow; if (total%numCols == 0) numPerRow = total / numCols; else numPerRow = (total+1)/numCols; if (numPerRow == 0) numPerRow = 1; bool printSeparator = false; bool printBetween = false; for (vector::iterator i = refs.begin(); i != refs.end(); ++i){ reference &r = *i; if (!(r.isPrivate()) && (r.creationTime > timeCutoff) && (((type == FOLDER_TYPE) && (r.isFolder())) || ((type != FOLDER_TYPE) && !(r.isFolder())))) { if (++skipped < startNum) continue; if (printSeparator){ output += separator + "\n"; printSeparator = false; } else if (printBetween) output += between + "\n"; else printBetween = true; output += r.sendAsHTML(printTemplate, varValues); if (++count >= maxNum) //enough in this. break; if (count%numPerRow == 0){ //add separator next time, if there is one! printSeparator = true; }; }; }; output += bottom; return output; } /**returns the contents of filename, replacing all includes with their contents, recursively. */ string fileView::getContents(const string & fileName){ // ifstream ifile(fileName.c_str()); iwebstream ifile(fileName); if (ifile == 0){ cerr << "Could not open input file " << fileName << endl; return ""; } cout << "Reading " << fileName << endl; string contents = ifile.getData(); // while (!ifile.eof()){ // contents += c; // c= ifile.get(); // } // ifile.close(); string::size_type includeStart = 0; string key = PLACEHOLDER + ":" + INCLUDE_TAG; //\n" + elvalues[num] + "\n\n"; else text = elvalues[num]; replaceAll(resultContents, key, text); }; return resultContents; }