/// <summary> /// Check source name from current query. /// </summary> /// <returns>True - source exists, False - error.</returns> public Boolean CheckSource() { var errMessage = ""; if (this.context.Request.Contains("source")) { var source = this.context.Request["source"]; if (BLANK(source)) { errMessage += "Empty source name!<br/>"; } else if (!TRequest.IsDomainName("source")) { errMessage += "Incorrect source name!<br/>"; } } if (errMessage.Length == 0) { return(true); } var prepare = new THashtable(); prepare["[#ErrMessage]"] = errMessage; this.Write("error", prepare); return(false); }
/// <summary> /// Update existing record by ID based on given fields. /// </summary> /// <param name="id">Unique record ID.</param> /// <param name="fields">The set of fields.</param> /// <returns>Result of SQL-query execution.</returns> public int UpdateById(Object id, THashtable fields) { var keys = new TEnumerator(fields.Keys.GetEnumerator()); var setValues = ""; Object[] pars = ARR(); var n = 0; while (keys.MoveNext()) { var key = (String)keys.GetCurrent(); if (key == this.idField) //TODO PHP { continue; } if (n != 0) { setValues += ", "; } setValues += CAT(key, " = ?"); pars = ADD(pars, this.SetFunction(key), fields[key]); n++; } pars = ADD(pars, this.SetFunction(this.idField), id); var query = Strings.Concat( " update ", this.tableName, " set ", setValues, " where (", this.idField, " = ?)" ); return(this.UpdateInternal(query, pars, "update")); }
/// <summary> /// Insert new record based on given fields. /// </summary> /// <param name="fields">The set of fields.</param> /// <returns>Result of SQL-query execution.</returns> public int Insert(THashtable fields) { var keys = new TEnumerator(fields.Keys.GetEnumerator()); var fieldNames = ""; var fieldValues = ""; Object[] pars = ARR(); //pars.SetPullValues(true); var n = 0; while (keys.MoveNext()) { var key = (String)keys.GetCurrent(); if (n != 0) { fieldNames += ", "; } if (n != 0) { fieldValues += ", "; } fieldNames += key; fieldValues += "?"; pars = ADD(pars, this.SetFunction(key), fields[key]); n++; } var query = Strings.Concat( " insert into ", this.tableName, " (", fieldNames, ") ", " values (", fieldValues, ")" ); return(this.UpdateInternal(query, pars, "insert")); }
/// <summary> /// Show template content by merging template and data. /// </summary> /// <param name="id">Template ID to use for merging.</param> /// <param name="hash">Data in the form of THashtable to use for merging.</param> /// <returns>Resulting content.</returns> public String ShowTemplate(String id, THashtable hash) { var ext = BLANK(this.context.Api) ? ".html" : (Config.API_FORMAT == "Xml"? ".xml" : ".txt"); var prefix = CAT(Config.FILE_PREFIX, "Bula/Fetcher/View/"); var filename = CAT(prefix, (BLANK(this.context.Api) ? "Html/" : (Config.API_FORMAT == "Xml"? "Xml/" : "Rest/")), id, ext); var template = this.GetTemplate(filename); var content = ""; var short_name = Strings.Replace("Bula/Fetcher/View/Html", "View", filename); if (!BLANK(Config.FILE_PREFIX)) { short_name = Strings.Replace(Config.FILE_PREFIX, "", short_name); } if (BLANK(this.context.Api)) { content += CAT(EOL, "<!-- BEGIN ", short_name, " -->", EOL); } if (!BLANK(template)) { content += this.ProcessTemplate(template, hash); } if (BLANK(this.context.Api)) { content += CAT("<!-- END ", short_name, " -->", EOL); } return(content); }
/// Execute main logic for DoTestItems action public override void Execute() { var insertRequired = false; var updateRequired = false; var doTime = new DOTime(this.context.Connection); var dsTimes = doTime.GetById(1); var timeShift = 240; // 4 min var currentTime = DateTimes.GetTime(); if (dsTimes.GetSize() > 0) { var oTime = dsTimes.GetRow(0); if (currentTime > DateTimes.GetTime(STR(oTime["d_Time"])) + timeShift) { updateRequired = true; } } else { insertRequired = true; } var from = (String)null; if (this.context.Request.Contains("from")) { from = this.context.Request["from"]; } this.context.Response.Write(TOP); if (updateRequired || insertRequired) { this.context.Response.Write(CAT("Fetching new items... Please wait...<br/>", EOL)); var boFetcher = new BOFetcher(this.context); boFetcher.FetchFromSources(from); doTime = new DOTime(this.context.Connection); // Need for DB reopen var fields = new THashtable(); fields["d_Time"] = DateTimes.Format(DateTimes.SQL_DTS, DateTimes.GetTime()); if (insertRequired) { fields["i_Id"] = 1; doTime.Insert(fields); } else { doTime.UpdateById(1, fields); } } else { this.context.Response.Write(CAT("<hr/>Fetch is not required<br/>", EOL)); } this.context.Response.Write(BOTTOM); }
/// <summary> /// Do actual merging of template and data. /// </summary> /// <param name="template">Template content.</param> /// <param name="hash">Data for merging with template.</param> /// <returns>Resulting content.</returns> public String FormatTemplate(String template, THashtable hash) { if (hash == null) { hash = new THashtable(); } String content1 = Strings.ReplaceInTemplate(template, hash); String content2 = Strings.ReplaceInTemplate(content1, this.context.GlobalConstants); return(content2); }
/// <summary> /// Get next record from the result of operation. /// </summary> /// <returns>Status of operation:</returns> /// 1 - next record exists. /// 0 - next record not exists. public int Next() { var arr = DataAccess.FetchArray(this.result); if (arr != null) { this.record = (THashtable)arr; return(1); } else { return(0); } }
/// Execute main logic for FilterItems block. public override void Execute() { var doSource = new DOSource(this.context.Connection); var source = (String)null; if (this.context.Request.Contains("source")) { source = this.context.Request["source"]; } var prepare = new THashtable(); if (this.context.FineUrls) { prepare["[#Fine_Urls]"] = 1; } prepare["[#Selected]"] = BLANK(source) ? " selected=\"selected\" " : ""; var dsSources = (DataSet)null; //TODO -- This can be too long on big databases... Switch off counters for now. var useCounters = true; if (useCounters) { dsSources = doSource.EnumSourcesWithCounters(); } else { dsSources = doSource.EnumSources(); } var options = new TArrayList(); for (int n = 0; n < dsSources.GetSize(); n++) { var oSource = dsSources.GetRow(n); var option = new THashtable(); option["[#Selected]"] = (oSource["s_SourceName"].Equals(source) ? "selected=\"selected\"" : " "); option["[#Id]"] = STR(oSource["s_SourceName"]); option["[#Name]"] = STR(oSource["s_SourceName"]); if (useCounters) { option["[#Counter]"] = oSource["cntpro"]; } options.Add(option); } prepare["[#Options]"] = options; this.Write("Pages/filter_items", prepare); }
/// <summary> /// Fetch data from the source. /// </summary> /// <param name="oSource">Source object.</param> /// <returns>Resulting items.</returns> /// <param name="from">Addition to feed URL (for testing purposes)</param> private Object[] FetchFromSource(THashtable oSource, String from) { var url = STR(oSource["s_Feed"]); if (url.Length == 0) { return(null); } if (!NUL(from)) { url = Strings.Concat(url, "&from=", from); } if (url.IndexOf("[#File_Ext]") != -1) { url = url.Replace("[#File_Ext]", Context.FILE_EXT); } var source = STR(oSource["s_SourceName"]); if (this.context.Request.Contains("m") && !source.Equals(this.context.Request["m"])) { return(null); } this.oLogger.Output(CAT("<br/>", EOL, "Started ")); //if (url.IndexOf("https") != -1) { // String encUrl = url.Replace("?", "%3F"); // encUrl = encUrl.Replace("&", "%26"); // url = Strings.Concat(Config.Site, "/get_ssl_rss.php?url=", encUrl); //} this.oLogger.Output(CAT("[[[", url, "]]]")); Object[] rss = Internal.FetchRss(url); if (rss == null) { this.oLogger.Output(CAT("-- problems --<br/>", EOL)); //problems++; //if (problems == 5) { // this.oLogger.Output(CAT("<br/>", EOL, "Too many problems... Stopped.<br/>", EOL)); // break; //} return(null); } return(rss); }
/// Execute main logic for Top block public override void Execute() { var prepare = new THashtable(); prepare["[#ImgWidth]"] = this.context.IsMobile ? 234 : 468; prepare["[#ImgHeight]"] = this.context.IsMobile ? 30 : 60; if (this.context.TestRun) { prepare["[#Date]"] = "28-Jun-2020 16:49 GMT"; } else { prepare["[#Date]"] = Util.ShowTime(); } this.Write("top", prepare); }
/// <summary> /// Check list from current query. /// </summary> /// <returns>True - checked OK, False - error.</returns> public Boolean CheckList() { if (this.context.Request.Contains("list")) { if (!TRequest.IsInteger(this.context.Request["list"])) { var prepare = new THashtable(); prepare["[#ErrMessage]"] = "Incorrect list number!"; this.Write("error", prepare); return(false); } } else { this.context.Request["list"] = "1"; } return(true); }
/// <summary> /// Initialize this BOItem. /// </summary> /// <param name="source">Current processed source.</param> /// <param name="item">Current processed RSS-item from given source.</param> private void Initialize(String source, THashtable item) { this.source = source; this.item = item; this.link = ((String)item["link"]).Trim(); // Pre-process full description & title // Trick to eliminate non-UTF-8 characters this.fullTitle = Strings.CleanChars((String)item["title"]); if (item.ContainsKey("description") && !BLANK(item["description"])) { this.fullDescription = Strings.CleanChars((String)item["description"]); this.fullDescription = Strings.Replace("\n", "\r\n", this.fullDescription); this.fullDescription = Strings.Replace("\r\r", "\r", this.fullDescription); } this.PreProcessLink(); }
/// <summary> /// Fetch next record from result. /// </summary> /// <param name="result">Query result</param> /// <returns>Next record</returns> public static THashtable FetchArray(Object result) { int pointer = (int)((Object[])result)[0]; System.Data.DataSet ds = (System.Data.DataSet)((Object[])result)[1]; if (pointer >= ds.Tables[0].Rows.Count) { return(null); // No more rows to fetch } THashtable hash = new THashtable(); System.Data.DataRow row = ds.Tables[0].Rows[pointer]; for (int n = 0; n < row.Table.Columns.Count; n++) { Object obj = row.ItemArray.GetValue(n); hash.Add(row.Table.Columns[n].ColumnName, obj is System.DBNull ? Bula.Objects.TNull.GetValue() : obj); } ((Object[])result)[0] = ++pointer; return(hash); }
/// <summary> /// Execute main logic for this action. /// </summary> /// <param name="linkToRedirect">Link to redirect (or null if there were some errors).</param> /// <param name="errorMessage">Error to show (or null if no errors).</param> public void ExecuteRedirect(String linkToRedirect, String errorMessage) { var prepare = new THashtable(); var templateName = (String)null; if (!NUL(errorMessage)) { prepare["[#Title]"] = "Error"; prepare["[#ErrMessage]"] = errorMessage; templateName = "error_alone"; } else if (!BLANK(linkToRedirect)) { prepare["[#Link]"] = linkToRedirect; templateName = "redirect"; } var engine = this.context.PushEngine(true); this.context.Response.Write(engine.ShowTemplate(templateName, prepare)); }
/// Execute main logic for Home block. public override void Execute() { var pars = this.Check(); if (pars == null) { return; } var prepare = new THashtable(); var doItem = new DOItem(this.context.Connection); prepare["[#BrowseItemsLink]"] = this.GetLink(Config.INDEX_PAGE, "?p=", null, "items"); if (Config.SHOW_IMAGES) { prepare["[#Show_Images]"] = 1; } var source = (String)null; var search = (String)null; var maxRows = Config.DB_HOME_ROWS; var dsItems = doItem.EnumItems(source, search, 1, maxRows); var rowCount = 1; var items = new TArrayList(); for (int n = 0; n < dsItems.GetSize(); n++) { var oItem = dsItems.GetRow(n); var row = FillItemRow(oItem, doItem.GetIdField(), rowCount); items.Add(row); rowCount++; } prepare["[#Items]"] = items; this.Write("Pages/home", prepare); }
/// <summary> /// Execute re-counting of categories. /// </summary> private void RecountCategories() { this.oLogger.Output(CAT("<br/>", EOL, "Recount categories ... ")); var doCategory = new DOCategory(this.context.Connection); var doItem = new DOItem(this.context.Connection); var dsCategories = doCategory.EnumCategories(); for (int n = 0; n < dsCategories.GetSize(); n++) { var oCategory = dsCategories.GetRow(n); var categoryId = STR(oCategory["s_CatId"]); var oldCounter = INT(oCategory["i_Counter"]); //String filter = STR(oCategory["s_Filter"]); //String sqlFilter = DOItem.BuildSqlByFilter(filter); var categoryName = STR(oCategory["s_Name"]); var sqlFilter = DOItem.BuildSqlByCategory(categoryName); var dsCounters = doItem.EnumIds(CAT("_this.b_Counted = 0 AND ", sqlFilter)); if (dsCounters.GetSize() == 0) { continue; } var newCounter = INT(dsCounters.GetSize()); //Update category var categoryFields = new THashtable(); categoryFields["i_Counter"] = oldCounter + newCounter; doCategory.UpdateById(categoryId, categoryFields); } doItem.Update("_this.b_Counted = 1", "_this.b_Counted = 0"); this.oLogger.Output(CAT(" ... Done<br/>", EOL)); }
/// <summary> /// Fast check of input query parameters. /// </summary> /// <returns>Parsed parameters (or null in case of any error).</returns> public THashtable Check() { var prepare = new THashtable(); if (!this.context.Request.Contains("id")) { prepare["[#ErrMessage]"] = "Item ID is required!"; this.Write("error", prepare); return(null); } var id = this.context.Request["id"]; if (!TRequest.IsInteger(id)) { prepare["[#ErrMessage]"] = "Item ID must be positive integer!"; this.Write("error", prepare); return(null); } var pars = new THashtable(); pars["id"] = id; return(pars); }
/// <summary> /// Parse data from the item. /// </summary> /// <param name="oSource">Source object.</param> /// <param name="item">Item object.</param> /// <returns>Result of executing SQL-query.</returns> private int ParseItemData(THashtable oSource, THashtable item) { // Load original values var sourceName = STR(oSource["s_SourceName"]); var sourceId = INT(oSource["i_SourceId"]); var boItem = new BOItem(sourceName, item); var pubDate = STR(item["pubDate"]); if (BLANK(pubDate) && !BLANK(item["dc"])) //TODO implement [dc][time] { var temp = (THashtable)item["dc"]; if (!BLANK(temp["date"])) { pubDate = STR(temp["date"]); item["pubDate"] = pubDate; } } boItem.ProcessMappings(this.dsMappings); boItem.ProcessDescription(); //boItem.ProcessCustomFields(); // Uncomment for processing custom fields boItem.ProcessCategory(); boItem.ProcessCreator(); // Process rules AFTER processing description (as some info can be extracted from it) boItem.ProcessRules(this.dsRules); if (BLANK(boItem.link)) //TODO - what we can do else? { return(0); } // Get date here as it can be extracted in rules processing if (boItem.date != null) { pubDate = boItem.date; } if (!BLANK(pubDate)) { pubDate = pubDate.Trim(); } var date = DateTimes.GmtFormat(DateTimes.SQL_DTS, DateTimes.FromRss(pubDate)); // Check whether item with the same link exists already var doItem = new DOItem(this.context.Connection); var dsItems = doItem.FindItemByLink(boItem.link, sourceId); if (dsItems.GetSize() > 0) { return(0); } // Try to add/embed standard categories from description var countCategories = boItem.AddStandardCategories(this.dsCategories, this.context.Lang); boItem.NormalizeCategories(); // Check the link once again after processing rules if (dsItems == null && !BLANK(boItem.link)) { doItem.FindItemByLink(boItem.link, sourceId); if (dsItems.GetSize() > 0) { return(0); } } var url = boItem.GetUrlTitle(true); //TODO -- Need to pass true if transliteration is required var fields = new THashtable(); fields["s_Link"] = boItem.link; fields["s_Title"] = boItem.title; fields["s_FullTitle"] = boItem.fullTitle; fields["s_Url"] = url; fields["i_Categories"] = countCategories; if (boItem.description != null) { fields["t_Description"] = boItem.description; } if (boItem.fullDescription != null) { fields["t_FullDescription"] = boItem.fullDescription; } fields["d_Date"] = date; fields["i_SourceLink"] = INT(oSource["i_SourceId"]); if (!BLANK(boItem.category)) { fields["s_Category"] = boItem.category; } if (!BLANK(boItem.creator)) { fields["s_Creator"] = boItem.creator; } if (!BLANK(boItem.custom1)) { fields["s_Custom1"] = boItem.custom1; } if (!BLANK(boItem.custom2)) { fields["s_Custom2"] = boItem.custom2; } var result = doItem.Insert(fields); return(result); }
/// <summary> /// Define global constants. /// </summary> private void DefineConstants() { this.GlobalConstants = new THashtable(); this.GlobalConstants["[#Site_Name]"] = Config.SITE_NAME; this.GlobalConstants["[#Site_Comments]"] = Config.SITE_COMMENTS; this.GlobalConstants["[#Top_Dir]"] = Config.TOP_DIR; if (!this.TestRun) { this.GlobalConstants["[#File_Ext]"] = FILE_EXT; } this.GlobalConstants["[#Index_Page]"] = this.TestRun ? Config.INDEX_PAGE : Strings.Replace("[#File_Ext]", FILE_EXT, Config.INDEX_PAGE); this.GlobalConstants["[#Action_Page]"] = this.TestRun ? Config.ACTION_PAGE : Strings.Replace("[#File_Ext]", FILE_EXT, Config.ACTION_PAGE); this.GlobalConstants["[#Rss_Page]"] = this.TestRun ? Config.RSS_PAGE : Strings.Replace("[#File_Ext]", FILE_EXT, Config.RSS_PAGE); //if (this.IsMobile) // this.GlobalConstants["[#Is_Mobile]"] = "1"; this.GlobalConstants["[#Lang]"] = this.Lang; System.Reflection.FieldInfo fieldInfo = typeof(Config).GetField("NAME_CATEGORY"); if (fieldInfo != null) { Set("Name_Category", fieldInfo.GetValue(null)); } fieldInfo = typeof(Config).GetField("NAME_CATEGORIES"); if (fieldInfo != null) { Set("Name_Categories", fieldInfo.GetValue(null)); } fieldInfo = typeof(Config).GetField("NAME_CREATOR"); if (fieldInfo != null) { Set("Name_Creator", fieldInfo.GetValue(null)); } fieldInfo = typeof(Config).GetField("NAME_CUSTOM1"); if (fieldInfo != null) { Set("Name_Custom1", fieldInfo.GetValue(null)); } fieldInfo = typeof(Config).GetField("NAME_CUSTOM2"); if (fieldInfo != null) { Set("Name_Custom2", fieldInfo.GetValue(null)); } // Map custom names this.GlobalConstants["[#Name_Item]"] = Config.NAME_ITEM; this.GlobalConstants["[#Name_Items]"] = Config.NAME_ITEMS; if (this.Contains("Name_Category")) { this.GlobalConstants["[#Name_Category]"] = this["Name_Category"]; } if (this.Contains("Name_Categories")) { this.GlobalConstants["[#Name_Categories]"] = this["Name_Categories"]; } if (this.Contains("Name_Creator")) { this.GlobalConstants["[#Name_Creator]"] = this["Name_Creator"]; } if (this.Contains("Name_Custom1")) { this.GlobalConstants["[#Name_Custom1]"] = this["Name_Custom1"]; } if (this.Contains("Name_Custom2")) { this.GlobalConstants["[#Name_Custom2]"] = this["Name_Custom2"]; } }
private int ProcessRule(String sourceName, THashtable rule) { var counter = 0; var nameTo = STR(rule["s_To"]); var valueTo = (String)null; var nameFrom = NUL(rule["s_From"]) ? nameTo : STR(rule["s_From"]); var valueFrom = STR(this.GetString(nameFrom)); var operation = STR(rule["s_Operation"]); var intValue = INT(rule["i_Value"]); var pattern = STR(rule["s_Pattern"]); var stringValue = STR(rule["s_Value"]); var append = false; if (EQ(operation, "get") && !NUL(valueFrom)) { valueTo = valueFrom; } else if (EQ(operation, "shrink") && !NUL(valueFrom) && LEN(pattern) > 0) { var shrinkIndex = valueFrom.IndexOf(pattern); if (shrinkIndex != -1) { valueTo = valueFrom.Substring(0, shrinkIndex).Trim(); } } else if (EQ(operation, "cut") && !NUL(valueFrom) && LEN(pattern) > 0) { var cutIndex = valueFrom.IndexOf(pattern); if (cutIndex != -1) { valueTo = valueFrom.Substring(cutIndex + LEN(pattern)); } } else if (EQ(operation, "replace") && !NUL(valueFrom) && LEN(pattern) > 0) { valueTo = Regex.Replace(valueFrom, pattern, stringValue, RegexOptions.IgnoreCase); } else if (EQ(operation, "remove") && !NUL(valueFrom) && LEN(pattern) > 0) { var matches = Regex.Matches(valueFrom, pattern, RegexOptions.IgnoreCase); if (SIZE(matches) > 0) { valueTo = valueFrom.Replace(matches[0].Value, ""); } } else if (EQ(operation, "truncate") && !NUL(valueFrom) && intValue > 0) { if (LEN(valueFrom) > intValue) { valueTo = valueFrom.Substring(0, intValue); while (!valueTo.EndsWith(" ")) { valueTo = valueTo.Substring(0, LEN(valueTo) - 1); } valueTo = valueTo += "..."; } } else if (EQ(operation, "extract") && !NUL(valueFrom)) { var matches = Regex.Matches(valueFrom, pattern, RegexOptions.IgnoreCase); var groups = matches.Count == 0 ? null : matches[0].Groups; if (SIZE(groups) > intValue) { if (BLANK(stringValue)) { valueTo = groups[intValue].Value; } else { if (EQ(nameTo, "date")) { valueTo = DateTimes.Format(DateTimes.RSS_DTS, DateTimes.Parse(stringValue, groups[intValue].Value)); } else { valueTo = stringValue; for (int n = 0; n < SIZE(groups); n++) { if (valueTo.IndexOf(CAT("$", n)) != -1) { valueTo = valueTo.Replace(CAT("$", n), groups[n].Value); } } } } if (EQ(nameTo, "category")) { append = true; } } } else if (EQ(operation, "map")) { //TODO } if (!NUL(valueTo)) { this.SetString(nameTo, valueTo, append); } return(counter); }
/// <summary> /// Fetch info from RSS-feed. /// </summary> /// <param name="url">Feed url</param> /// <returns>Resulting array of items</returns> public static Object[] FetchRss(String url) { var items = new TArrayList(); XmlDocument rssXmlDoc = new XmlDocument(); XmlNamespaceManager nsmgr = new XmlNamespaceManager(rssXmlDoc.NameTable); nsmgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/"); // Load the RSS file from the RSS URL try { rssXmlDoc.Load(url); } catch (Exception ex1) { var matchCollection = Regex.Matches(ex1.Message, "'([^']+)' is an undeclared prefix. Line [0-9]+, position [0-9]+."); if (matchCollection.Count > 0) { var prefix = matchCollection[0].Groups[1].Value; try { var client = new System.Net.WebClient(); var content = (new System.Net.WebClient()).DownloadString(url); byte[] bytes = Encoding.Default.GetBytes(content); content = Encoding.UTF8.GetString(bytes); //content = System.Text.Encoding.UTF8.GetBytes(content).ToString(); var pattern = CAT("<", prefix, ":[^>]+>[^<]+</", prefix, ":[^>]+>"); content = Regex.Replace(content, pattern, ""); rssXmlDoc.LoadXml(content); } catch (Exception ex2) { return(null); } } else { return(null); } } // Parse the Items in the RSS file XmlNodeList rssNodes = rssXmlDoc.SelectNodes("rss/channel/item"); // Iterate through the items in the RSS file foreach (XmlNode rssNode in rssNodes) { var item = new THashtable(); XmlNodeList itemNodes = rssNode.SelectNodes("*"); foreach (XmlNode itemNode in itemNodes) { String name = itemNode.Name; String text = itemNode.InnerXml; if (text.StartsWith("<![CDATA[")) { text = text.Replace("<![CDATA[", "").Replace("]]>", ""); } if (name == "category") { if (item[name] == null) { item[name] = text; } else { item[name] += ", " + text; } } else if (name == "dc:creator") { THashtable dc = item.ContainsKey("dc") ? (THashtable)item["dc"] : new THashtable(); dc["creator"] = text; item["dc"] = dc; } else if (name == "dc:date") { THashtable dc = item.ContainsKey("dc") ? (THashtable)item["dc"] : new THashtable(); dc["date"] = text; item["dc"] = dc; } else { item[name] = text; } } items.Add(item); } return(items.ToArray()); }
/// <summary> /// Instantiate BOItem from given source and RSS-item. /// </summary> /// <param name="source">Current processed source.</param> /// <param name="item">Current processed RSS-item from given source.</param> public BOItem(String source, THashtable item) { this.Initialize(source, item); }
/// Execute main logic for Index block public override void Execute() { if (pagesArray == null) { Initialize(); } DataAccess.SetErrorDelegate(context.Response.End); var pageInfo = this.context.Request.TestPage(pagesArray, "home"); // Test action name if (!pageInfo.ContainsKey("page")) { this.context.Response.End("Error in parameters -- no page"); return; } var pageName = (String)pageInfo["page"]; var className = (String)pageInfo["class"]; //this.context.Request.Initialize(); if (INT(pageInfo["post_required"]) == 1) { this.context.Request.ExtractPostVars(); } else { this.context.Request.ExtractAllVars(); } //echo "In Index -- " . Print_r(this, true); this.context["Page"] = pageName; var apiName = (String)pageInfo["api"]; this.context.Api = BLANK(apiName) ? "" : apiName; // Blank (html) or "rest" for now var engine = this.context.PushEngine(true); var prepare = new THashtable(); prepare["[#Site_Name]"] = Config.SITE_NAME; var pFromVars = this.context.Request.Contains("p") ? this.context.Request["p"] : "home"; var idFromVars = this.context.Request.Contains("id") ? this.context.Request["id"] : null; var title = Config.SITE_NAME; if (pFromVars != "home") { title = CAT(title, " :: ", pFromVars, (!NUL(idFromVars) ? CAT(" :: ", idFromVars) : null)); } prepare["[#Title]"] = title; //TODO -- need unique title on each page prepare.Put("[#Keywords]", this.context.TestRun ? Config.SITE_KEYWORDS : Strings.Replace("[#Platform]", Config.PLATFORM, Config.SITE_KEYWORDS) ); prepare.Put("[#Description]", this.context.TestRun ? Config.SITE_DESCRIPTION : Strings.Replace("[#Platform]", Config.PLATFORM, Config.SITE_DESCRIPTION) ); prepare["[#Styles]"] = CAT( (this.context.TestRun ? null : Config.TOP_DIR), this.context.IsMobile ? "styles2" : "styles"); prepare["[#ContentType]"] = "text/html; charset=UTF-8"; prepare["[#Top]"] = engine.IncludeTemplate("Top"); prepare["[#Menu]"] = engine.IncludeTemplate("Menu"); // Get included page either from cache or build it from the scratch var errorContent = engine.IncludeTemplate(CAT("Pages/", className), "check"); if (!BLANK(errorContent)) { prepare["[#Page]"] = errorContent; } else { if (Config.CACHE_PAGES /* && !Config.DontCache.Contains(pageName)*/) //TODO!!! { prepare["[#Page]"] = Util.ShowFromCache(engine, this.context.CacheFolder, pageName, className); } else { prepare["[#Page]"] = engine.IncludeTemplate(CAT("Pages/", className)); } } if (/*Config.RssAllowed != null && */ Config.SHOW_BOTTOM) { // Get bottom block either from cache or build it from the scratch if (Config.CACHE_PAGES) { prepare["[#Bottom]"] = Util.ShowFromCache(engine, this.context.CacheFolder, BLANK(apiName) ? "bottom" : CAT(apiName, "_bottom"), "Bottom"); } else { prepare["[#Bottom]"] = engine.IncludeTemplate("Bottom"); } } prepare.Put("[#Github_Repo]", this.context.TestRun ? Config.GITHUB_REPO : Strings.Replace("[#Platform]", Strings.ToLowerCase(Config.PLATFORM), Config.GITHUB_REPO) ); prepare.Put("[#Powered_By]", this.context.TestRun ? Config.POWERED_BY : Strings.Replace("[#Platform]", Config.PLATFORM, Config.POWERED_BY) ); this.context.Response.WriteHeader("Content-type", CAT( (BLANK(apiName) ? "text/html" : Config.API_CONTENT), "; charset=UTF-8") ); this.Write("index", prepare); // Fix <title> //TODO -- comment for now //newTitle = Util.ExtractInfo(content, "<input type=\"hidden\" name=\"s_Title\" value=\"", "\" />"); //if (!BLANK(newTitle)) // content = Regex.Replace(content, "<title>(.*?)</title>", CAT("<title>", Config.SITE_NAME, " -- ", newTitle, "</title>"), RegexOptions.IgnoreCase); this.context.Response.Write(engine.GetPrintString()); this.context.Response.End(); }
/// Execute main logic for View Item block. public override void Execute() { var pars = Check(); if (pars == null) { return; } var id = (String)pars["id"]; var prepare = new THashtable(); var doItem = new DOItem(this.context.Connection); var dsItems = doItem.GetById(INT(id)); if (dsItems == null || dsItems.GetSize() == 0) { prepare["[#ErrMessage]"] = "Wrong item ID!"; this.Write("error", prepare); return; } var oItem = dsItems.GetRow(0); var title = STR(oItem["s_Title"]); var sourceName = STR(oItem["s_SourceName"]); this.context["Page_Title"] = title; var leftWidth = "25%"; if (this.context.IsMobile) { leftWidth = "20%"; } var idField = doItem.GetIdField(); if (Config.SHOW_IMAGES) { prepare["[#Show_Images]"] = 1; } prepare["[#RedirectLink]"] = this.GetLink(Config.ACTION_PAGE, "?p=do_redirect_item&id=", "redirect/item/", oItem[idField]); prepare["[#LeftWidth]"] = leftWidth; prepare["[#Title]"] = Util.Show(title); prepare["[#InputTitle]"] = Util.Safe(title); prepare["[#RedirectSource]"] = this.GetLink(Config.ACTION_PAGE, "?p=do_redirect_source&source=", "redirect/source/", sourceName); prepare["[#SourceName]"] = sourceName; prepare["[#ExtImages]"] = Config.EXT_IMAGES; prepare["[#SourceLink]"] = this.GetLink(Config.INDEX_PAGE, "?p=items&source=", "items/source/", sourceName); prepare["[#Date]"] = Util.ShowTime(STR(oItem["d_Date"])); if (!NUL(oItem["s_Creator"])) { prepare["[#Creator]"] = STR(oItem["s_Creator"]); } if (oItem.ContainsKey("t_Description") && !BLANK(STR(oItem["t_Description"]))) { prepare["[#Description]"] = Util.Show(STR(oItem["t_Description"])); } prepare["[#ItemID]"] = oItem[idField]; if (this.context.Contains("Name_Category") && !NUL(oItem["s_Category"])) { prepare["[#Category]"] = oItem["s_Category"]; } if (this.context.Contains("Name_Custom1") && !NUL(oItem["s_Custom1"])) { prepare["[#Custom1]"] = oItem["s_Custom1"]; } if (this.context.Contains("Name_Custom2") && !NUL(oItem["s_Custom2"])) { prepare["[#Custom2]"] = oItem["s_Custom2"]; } if (this.context.Lang == "ru" && !this.context.IsMobile) { prepare["[#Share]"] = 1; } var engine = this.context.GetEngine(); if (Config.CACHE_PAGES) { prepare["[#Home]"] = Util.ShowFromCache(engine, this.context.CacheFolder, "home", "Home", "p=home&from_view_item=1"); } else { prepare["[#Home]"] = engine.IncludeTemplate("Pages/Home"); } this.Write("Pages/view_item", prepare); }
/// Execute main logic for Bottom block public override void Execute() { var prepare = new THashtable(); prepare.Put("[#Items_By_Category]", CAT(Config.NAME_ITEMS, "_by_", this.context["Name_Category"])); var doCategory = new DOCategory(this.context.Connection); var dsCategory = doCategory.EnumAll(Config.SHOW_EMPTY ? null : "_this.i_Counter <> 0", Config.SORT_CATEGORIES == null ? null : CAT("_this.", Config.SORT_CATEGORIES)); var size = dsCategory.GetSize(); int size3 = size % 3; int n1 = INT(size / 3) + (size3 == 0 ? 0 : 1); int n2 = n1 * 2; Object[] nn = ARR(0, n1, n2, size); var filterBlocks = new TArrayList(); for (int td = 0; td < 3; td++) { var filterBlock = new THashtable(); var rows = new TArrayList(); for (int n = INT(nn[td]); n < INT(nn[td + 1]); n++) { var oCategory = dsCategory.GetRow(n); if (NUL(oCategory)) { continue; } var counter = INT(oCategory["i_Counter"]); if (Config.SHOW_EMPTY == false && INT(counter) == 0) { continue; } var key = STR(oCategory["s_CatId"]); var name = STR(oCategory["s_Name"]); var row = new THashtable(); row["[#Link]"] = this.GetLink(Config.INDEX_PAGE, "?p=items&filter=", "items/filter/", key); row["[#LinkText]"] = name; //if (counter > 0) row["[#Counter]"] = counter; rows.Add(row); } filterBlock["[#Rows]"] = rows; filterBlocks.Add(filterBlock); } prepare["[#FilterBlocks]"] = filterBlocks; if (!this.context.IsMobile) { //dsCategory = doCategory.EnumAll(null, Config.SORT_CATEGORIES == null ? null : CAT("_this.", Config.SORT_CATEGORIES)); size = dsCategory.GetSize(); //50 size3 = size % 3; //2 n1 = INT(size / 3) + (size3 == 0 ? 0 : 1); //17.3 n2 = n1 * 2; //34.6 nn = ARR(0, n1, n2, size); var rssBlocks = new TArrayList(); for (int td = 0; td < 3; td++) { var rssBlock = new THashtable(); var rows = new TArrayList(); for (int n = INT(nn[td]); n < INT(nn[td + 1]); n++) { var oCategory = dsCategory.GetRow(n); if (NUL(oCategory)) { continue; } var key = STR(oCategory["s_CatId"]); var name = STR(oCategory["s_Name"]); //counter = INT(oCategory["i_Counter"]); var row = new THashtable(); row["[#Link]"] = this.GetLink(Config.RSS_PAGE, "?filter=", "rss/", CAT(key, (this.context.FineUrls ? ".xml" : null))); row["[#LinkText]"] = name; rows.Add(row); } rssBlock["[#Rows]"] = rows; rssBlocks.Add(rssBlock); } prepare["[#RssBlocks]"] = rssBlocks; } this.Write("bottom", prepare); }
/// <summary> /// Execute template processing. /// </summary> /// <param name="template">Template in form of the list of lines.</param> /// <param name="hash">Data for merging with template.</param> /// <returns>Resulting content.</returns> private String ProcessTemplate(TArrayList template, THashtable hash) { if (this.context.IsMobile) { if (hash == null) { hash = new THashtable(); } hash["[#Is_Mobile]"] = 1; } var trimLine = true; var trimEnd = EOL; var ifMode = 0; var repeatMode = 0; var ifBuf = new TArrayList(); var repeatBuf = new TArrayList(); var ifWhat = ""; var repeatWhat = ""; var content = ""; for (int n = 0; n < template.Size(); n++) { var line = (String)template[n]; var lineNoComments = TrimComments(line); //, BLANK(this.context.Api)); //TODO if (ifMode > 0) { if (lineNoComments.IndexOf("#if") == 0) { ifMode++; } if (lineNoComments.IndexOf("#end if") == 0) { if (ifMode == 1) { var not = (ifWhat.IndexOf("!") == 0); var eq = (ifWhat.IndexOf("==") != -1); var neq = (ifWhat.IndexOf("!=") != -1); var processFlag = false; if (not == true) { if (!hash.ContainsKey(ifWhat.Substring(1))) //TODO { processFlag = true; } } else { if (eq) { String[] ifWhatArray = Strings.Split("==", ifWhat); String ifWhat1 = ifWhatArray[0]; String ifWhat2 = ifWhatArray[1]; if (hash.ContainsKey(ifWhat1) && EQ(hash[ifWhat1], ifWhat2)) { processFlag = true; } } else if (neq) { String[] ifWhatArray = Strings.Split("!=", ifWhat); String ifWhat1 = ifWhatArray[0]; String ifWhat2 = ifWhatArray[1]; if (hash.ContainsKey(ifWhat1) && !EQ(hash[ifWhat1], ifWhat2)) { processFlag = true; } } else if (hash.ContainsKey(ifWhat)) { processFlag = true; } } if (processFlag) { content += ProcessTemplate(ifBuf, hash); } ifBuf = new TArrayList(); } else { ifBuf.Add(line); } ifMode--; } else { ifBuf.Add(line); } } else if (repeatMode > 0) { if (lineNoComments.IndexOf("#repeat") == 0) { repeatMode++; } if (lineNoComments.IndexOf("#end repeat") == 0) { if (repeatMode == 1) { if (hash.ContainsKey(repeatWhat)) { var rows = (TArrayList)hash[repeatWhat]; for (int r = 0; r < rows.Size(); r++) { content += ProcessTemplate(repeatBuf, (THashtable)rows[r]); } hash.Remove(repeatWhat); } repeatBuf = new TArrayList(); } else { repeatBuf.Add(line); } repeatMode--; } else { repeatBuf.Add(line); } } else { if (lineNoComments.IndexOf("#if") == 0) { ifMode = repeatMode > 0 ? 2 : 1; ifWhat = lineNoComments.Substring(4).Trim(); } else if (lineNoComments.IndexOf("#repeat") == 0) { repeatMode++; repeatWhat = lineNoComments.Substring(8).Trim(); repeatBuf = new TArrayList(); } else { if (trimLine) { line = line.Trim(); line += trimEnd; } content += line; } } } var result = FormatTemplate(content, hash); return(result); }
/// Execute main logic for Items block. public override void Execute() { var pars = this.Check(); if (pars == null) { return; } var list = (String)pars["list"]; var listNumber = list == null ? 1 : INT(list); var sourceName = (String)pars["source_name"]; var filterName = (String)pars["filter_name"]; var errorMessage = ""; var filter = (String)null; var category = (String)null; if (!NUL(filterName)) { var doCategory = new DOCategory(this.context.Connection); THashtable[] oCategory = { new THashtable() }; if (!doCategory.CheckFilterName(filterName, oCategory)) { errorMessage += "Non-existing filter name!"; } else { category = STR(oCategory[0]["s_Name"]); filter = STR(oCategory[0]["s_Filter"]); } } var sourceId = -1; if (!NUL(sourceName)) { var doSource = new DOSource(this.context.Connection); THashtable[] oSource = { new THashtable() }; if (!doSource.CheckSourceName(sourceName, oSource)) { if (errorMessage.Length > 0) { errorMessage += "<br/>"; } errorMessage += "Non-existing source name!"; } else { sourceId = INT(oSource[0]["i_SourceId"]); } } var engine = this.context.GetEngine(); var prepare = new THashtable(); if (errorMessage.Length > 0) { prepare["[#ErrMessage]"] = errorMessage; this.Write("error", prepare); return; } if (Config.SHOW_IMAGES) { prepare["[#Show_Images]"] = 1; } prepare["[#ColSpan]"] = Config.SHOW_IMAGES ? 4 : 3; // Uncomment to enable filtering by source and/or category prepare["[#FilterItems]"] = engine.IncludeTemplate("Pages/FilterItems"); var s_Title = CAT( "Browse ", Config.NAME_ITEMS, (this.context.IsMobile ? "<br/>" : null), (!BLANK(sourceName) ? CAT(" ... from '", sourceName, "'") : null), (!BLANK(filter) ? CAT(" ... for '", category, "'") : null) ); prepare["[#Title]"] = s_Title; var maxRows = Config.DB_ITEMS_ROWS; var doItem = new DOItem(this.context.Connection); //String realFilter = DOItem.BuildSqlByFilter(filter); var realFilter = DOItem.BuildSqlByCategory(category); var dsItems = doItem.EnumItems(sourceName, realFilter, listNumber, maxRows); var listTotal = dsItems.GetTotalPages(); if (listNumber > listTotal) { if (listTotal > 0) { prepare["[#ErrMessage]"] = "List number is too large!"; this.Write("error", prepare); return; } else { prepare["[#ErrMessage]"] = "Empty list!"; this.Write("error", prepare); return; } } if (listTotal > 1) { prepare["[#List_Total]"] = listTotal; prepare["[#List]"] = listNumber; } var count = 1; var rows = new TArrayList(); for (int n = 0; n < dsItems.GetSize(); n++) { var oItem = dsItems.GetRow(n); var row = FillItemRow(oItem, doItem.GetIdField(), count); count++; rows.Add(row); } prepare["[#Rows]"] = rows; if (listTotal > 1) { var chunk = 2; var before = false; var after = false; var pages = new TArrayList(); for (int n = 1; n <= listTotal; n++) { var page = new THashtable(); if (n < listNumber - chunk) { if (!before) { before = true; page["[#Text]"] = "1"; page["[#Link]"] = GetPageLink(1); pages.Add(page); page = new THashtable(); page["[#Text]"] = " ... "; //row.Remove("[#Link]"); pages.Add(page); } continue; } if (n > listNumber + chunk) { if (!after) { after = true; page["[#Text]"] = " ... "; pages.Add(page); page = new THashtable(); page["[#Text]"] = listTotal; page["[#Link]"] = GetPageLink(listTotal); pages.Add(page); } continue; } if (listNumber == n) { page["[#Text]"] = CAT("=", n, "="); pages.Add(page); } else { if (n == 1) { page["[#Link]"] = GetPageLink(1); page["[#Text]"] = 1; } else { page["[#Link]"] = GetPageLink(n); page["[#Text]"] = n; } pages.Add(page); } } prepare["[#Pages]"] = pages; } this.Write("Pages/items", prepare); }
/// Execute main logic for Menu block public override void Execute() { var publicPages = new TArrayList(); var bookmark = (String)null; if (this.context.Contains("Name_Category")) { bookmark = CAT("#", Config.NAME_ITEMS, "_by_", this.context["Name_Category"]); } publicPages.Add("Home"); publicPages.Add("home"); if (this.context.IsMobile) { publicPages.Add(Config.NAME_ITEMS); publicPages.Add("items"); if (Config.SHOW_BOTTOM && this.context.Contains("Name_Category")) { publicPages.Add(CAT("By ", this.context["Name_Category"])); publicPages.Add(bookmark); //publicPages.Add("RSS Feeds"); //publicPages.Add("#read_rss_feeds"); } publicPages.Add("Sources"); publicPages.Add("sources"); } else { publicPages.Add(CAT("Browse ", Config.NAME_ITEMS)); publicPages.Add("items"); if (Config.SHOW_BOTTOM && this.context.Contains("Name_Category")) { publicPages.Add(CAT(Config.NAME_ITEMS, " by ", this.context["Name_Category"])); publicPages.Add(bookmark); publicPages.Add("Read RSS Feeds"); publicPages.Add("#Read_RSS_Feeds"); } publicPages.Add("Sources"); publicPages.Add("sources"); } var menuItems = new TArrayList(); for (int n = 0; n < publicPages.Size(); n += 2) { var row = new THashtable(); var title = STR(publicPages[n + 0]); var page = STR(publicPages[n + 1]); var href = (String)null; if (EQ(page, "home")) { href = Config.TOP_DIR; } else { if (EQ(page.Substring(0, 1), "#")) { href = page; } else { href = this.GetLink(Config.INDEX_PAGE, "?p=", null, page); } } row["[#Link]"] = href; row["[#LinkText]"] = title; row["[#Prefix]"] = n != 0 ? " • " : " "; menuItems.Add(row); } var prepare = new THashtable(); prepare["[#MenuItems]"] = menuItems; this.Write("menu", prepare); }
/// <summary> /// Merge template with variables and write to engine. /// </summary> /// <param name="template">Template name.</param> /// <param name="prepare">Prepared variables.</param> public void Write(String template, THashtable prepare) { var engine = this.context.GetEngine(); engine.Write(engine.ShowTemplate(template, prepare)); }
/// <summary> /// Fast check of input query parameters. /// </summary> /// <returns>Parsed parameters (or null in case of any error).</returns> public THashtable Check() { var errorMessage = ""; var list = this.context.Request["list"]; if (!NUL(list)) { if (BLANK(list)) { errorMessage += "Empty list number!"; } else if (!TRequest.IsInteger(list)) { errorMessage += "Incorrect list number!"; } } var sourceName = this.context.Request["source"]; if (!NUL(sourceName)) { if (BLANK(sourceName)) { if (errorMessage.Length > 0) { errorMessage += "<br/>"; } errorMessage += "Empty source name!"; } else if (!TRequest.IsDomainName(sourceName)) { if (errorMessage.Length > 0) { errorMessage += "<br/>"; } errorMessage += "Incorrect source name!"; } } var filterName = this.context.Request["filter"]; if (!NUL(filterName)) { if (BLANK(filterName)) { if (errorMessage.Length > 0) { errorMessage += "<br/>"; } errorMessage += "Empty filter name!"; } else if (!TRequest.IsName(filterName)) { if (errorMessage.Length > 0) { errorMessage += "<br/>"; } errorMessage += "Incorrect filter name!"; } } if (errorMessage.Length > 0) { var prepare = new THashtable(); prepare["[#ErrMessage]"] = errorMessage; this.Write("error", prepare); return(null); } var pars = new THashtable(); if (!NUL(list)) { pars["list"] = list; } if (!NUL(sourceName)) { pars["source_name"] = sourceName; } if (!NUL(filterName)) { pars["filter_name"] = filterName; } return(pars); }