/********************************************************************************** * nWordPress is an automated migration of WordPress 2.5.1 performed by Numiton. * * copyright : (C) 2008 Numiton - www.numiton.com * email : numiton@users.sourceforge.net * * $Id: RssPage.java,v 1.4 2008/10/14 13:15:48 numiton Exp $ * **********************************************************************************/ /********************************************************************************** * * 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 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. * ***************************************************************************/ package org.numiton.nwp.wp_includes; import static com.numiton.PhpCommonConstants.BOOLEAN_FALSE; import static com.numiton.VarHandling.*; import static com.numiton.generic.PhpWeb.*; import java.io.IOException; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.numiton.nwp.NumitonController; import org.numiton.nwp.wp_includes.js.tinymce.plugins.spellchecker.includes.GeneralPage; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.numiton.DateTime; import com.numiton.array.Array; import com.numiton.array.ArrayEntry; import com.numiton.error.ErrorHandling; import com.numiton.generic.ListAssigner; import com.numiton.generic.PhpWebEnvironment; import com.numiton.ntile.til.libraries.php.quercus.QRegExPerl; import com.numiton.ntile.til.libraries.php.quercus.QStrings; import com.numiton.string.Strings; @Controller @Scope("request") public class RssPage extends NumitonController { protected static final Logger LOG = Logger.getLogger(RssPage.class.getName()); /** * Generated in place of local variable 'field' from method * '_response_to_rss' because it is used inside an inner class. */ Object _response_to_rss_field = null; /** * Generated in place of local variable 'val' from method '_response_to_rss' * because it is used inside an inner class. */ String _response_to_rss_val = null; /** * Generated in place of local variable 'year' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_year; /** * Generated in place of local variable 'month' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_month; /** * Generated in place of local variable 'day' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_day; /** * Generated in place of local variable 'hours' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_hours; /** * Generated in place of local variable 'minutes' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_minutes; /** * Generated in place of local variable 'seconds' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_seconds; /** * Generated in place of local variable 'tz_mod' from method 'parse_w3cdtf' * because it is used inside an inner class. */ Object parse_w3cdtf_tz_mod = null; /** * Generated in place of local variable 'tz_hour' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_tz_hour = 0; /** * Generated in place of local variable 'tz_min' from method 'parse_w3cdtf' * because it is used inside an inner class. */ int parse_w3cdtf_tz_min = 0; @Override @RequestMapping("/wp-includes/rss.php") public ModelAndView execute(HttpServletRequest javaRequest, HttpServletResponse javaResponse) throws IOException { return super.execute(javaRequest, javaResponse); } @Override public String getViewName() { return "wp_includes/rss"; } public MagpieRSS fetch_rss(String url) { Snoopy resp = null; RSSCache cache = null; String cache_status; Array<Object> request_headers = new Array<Object>(); MagpieRSS rss = null; String errormsg = null; String http_error = null; // initialize constants init(); if (!isset(url)) { // error("fetch_rss called without a url"); return null; } // if cache is disabled if (!booleanval(gConsts.getMAGPIE_CACHE_ON())) { // fetch file, and parse it resp = _fetch_remote_file(url, ""); if (is_success(resp.status)) { return _response_to_rss(resp); } else { // error("Failed to fetch $url and cache is off"); return null; } } // else cache is ON else { // Flow // 1. check cache // 2. if there is a hit, make sure its fresh // 3. if cached obj fails freshness check, fetch remote // 4. if remote fails, return stale object, or error cache = new RSSCache(gVars, gConsts, gConsts.getMAGPIE_CACHE_DIR(), gConsts.getMAGPIE_CACHE_AGE()); if (booleanval(gConsts.getMAGPIE_DEBUG()) && booleanval(cache.ERROR)) { getIncluded(GeneralPage.class, gVars, gConsts).debug(cache.ERROR, ErrorHandling.E_USER_WARNING); } cache_status = ""; // response of check_cache request_headers = new Array<Object>(); // HTTP headers to send with fetch rss = null; // parsed RSS object errormsg = strval(0); // errors, if any if (!booleanval(cache.ERROR)) { // return cache HIT, MISS, or STALE cache_status = cache.check_cache(url); } // if object cached, and cache is fresh, return cached obj if (equal(cache_status, "HIT")) { rss = (MagpieRSS) cache.get(url); if (isset(rss) && booleanval(rss)) { rss.from_cache = 1; if (gConsts.getMAGPIE_DEBUG() > 1) { getIncluded(GeneralPage.class, gVars, gConsts).debug("MagpieRSS: Cache HIT", ErrorHandling.E_USER_NOTICE); } return rss; } } // else attempt a conditional get // setup headers if (equal(cache_status, "STALE")) { rss = (MagpieRSS) cache.get(url); if (booleanval(rss) && booleanval(rss.etag) && booleanval(rss.last_modified)) { request_headers.putValue("If-None-Match", Strings.trim(rss.etag, "\"\n\r")); //Modified by Numiton request_headers.putValue("If-Last-Modified", rss.last_modified); } } resp = _fetch_remote_file(url, request_headers); if (isset(resp) && booleanval(resp)) { if (equal(resp.status, "304")) { // we have the most current copy if (gConsts.getMAGPIE_DEBUG() > 1) { getIncluded(GeneralPage.class, gVars, gConsts).debug("Got 304 for " + url); } // reset cache on 304 (at minutillo insistent prodding) cache.set(url, rss); return rss; } else if (is_success(resp.status)) { rss = _response_to_rss(resp); if (booleanval(rss)) { if (gConsts.getMAGPIE_DEBUG() > 1) { getIncluded(GeneralPage.class, gVars, gConsts).debug("Fetch successful"); } // add object to cache cache.set(url, rss); return rss; } } else { errormsg = "Failed to fetch " + url + ". "; if (booleanval(resp.error)) { // compensate for Snoopy's annoying habbit to tacking // on '\n' http_error = Strings.substr(resp.error, 0, -2); errormsg = errormsg + "(HTTP Error: " + http_error + ")"; } else { errormsg = errormsg + "(HTTP Response: " + resp.response_code + ")"; } } } else { errormsg = "Unable to retrieve RSS file for unknown reasons."; } // else fetch failed // attempt to return cached object if (booleanval(rss)) { if (booleanval(gConsts.getMAGPIE_DEBUG())) { getIncluded(GeneralPage.class, gVars, gConsts).debug("Returning STALE object for " + url); } return rss; } // else we totally failed // error( $errormsg ); return null; } // end if ( !MAGPIE_CACHE_ON ) { } // end fetch_rss() public Snoopy _fetch_remote_file(String url, Object headers)/* Do not change type */ { Snoopy client = null; // Snoopy is an HTTP client in PHP client = new Snoopy(gVars, gConsts); client.agent = gConsts.getMAGPIE_USER_AGENT(); client.read_timeout = gConsts.getMAGPIE_FETCH_TIME_OUT(); client.use_gzip = gConsts.getMAGPIE_USE_GZIP(); if (is_array(headers)) { client.rawheaders = (Array<Object>) headers; } client.fetch(url); return client; } public MagpieRSS _response_to_rss(Snoopy resp) { MagpieRSS rss = null; String h = null; String errormsg = null; rss = new MagpieRSS(gVars, gConsts, strval(resp.results)); // if RSS parsed successfully if (booleanval(rss) && !booleanval(rss.ERROR)) { // find Etag, and Last-Modified for (Map.Entry javaEntry588 : resp.headers.entrySet()) { h = strval(javaEntry588.getValue()); // 2003-03-02 - Nicola Asuni (www.tecnick.com) - fixed bug "Undefined offset: 1" if (BOOLEAN_FALSE != Strings.strpos(h, ": ")) { new ListAssigner<String>() { public Array<String> doAssign(Array<String> srcArray) { if (strictEqual(srcArray, null)) { return null; } _response_to_rss_field = srcArray.getValue(0); _response_to_rss_val = srcArray.getValue(1); return srcArray; } }.doAssign(Strings.explode(": ", h, 2)); } else { _response_to_rss_field = h; _response_to_rss_val = ""; } if (equal(_response_to_rss_field, "ETag")) { rss.etag = _response_to_rss_val; } if (equal(_response_to_rss_field, "Last-Modified")) { rss.last_modified = _response_to_rss_val; } } return rss; } // else construct error message else { errormsg = "Failed to parse RSS file."; if (booleanval(rss)) { errormsg = errormsg + " (" + rss.ERROR + ")"; } // error($errormsg); return null; } // end if ($rss and !$rss->error) } /*=======================================================================*\ Function: init Purpose: setup constants with default values check for user overrides \*=======================================================================*/ public void init() { String ua = null; if (gConsts.isMAGPIE_INITALIZEDDefined()) { return; } else { gConsts.setMAGPIE_INITALIZED(1); } if (!gConsts.isMAGPIE_CACHE_ONDefined()) { gConsts.setMAGPIE_CACHE_ON(1); } if (!gConsts.isMAGPIE_CACHE_DIRDefined()) { gConsts.setMAGPIE_CACHE_DIR("./cache"); } if (!gConsts.isMAGPIE_CACHE_AGEDefined()) { gConsts.setMAGPIE_CACHE_AGE(60 * 60); // one hour } if (!gConsts.isMAGPIE_CACHE_FRESH_ONLYDefined()) { gConsts.setMAGPIE_CACHE_FRESH_ONLY(0); } if (!gConsts.isMAGPIE_DEBUGDefined()) { gConsts.setMAGPIE_DEBUG(0); } if (!gConsts.isMAGPIE_USER_AGENTDefined()) { ua = "nWordPress/" + gVars.wp_version; if (booleanval(gConsts.getMAGPIE_CACHE_ON())) { ua = ua + ")"; } else { ua = ua + "; No cache)"; } gConsts.setMAGPIE_USER_AGENT(ua); } if (!gConsts.isMAGPIE_FETCH_TIME_OUTDefined()) { gConsts.setMAGPIE_FETCH_TIME_OUT(2); // 2 second timeout } // use gzip encoding to fetch rss files if supported? if (!gConsts.isMAGPIE_USE_GZIPDefined()) { gConsts.setMAGPIE_USE_GZIP(true); } } public boolean is_info(Object sc) { return (intval(sc) >= 100) && (intval(sc) < 200); } public boolean is_success(int sc) { return (sc >= 200) && (sc < 300); } public boolean is_redirect(Object sc) { return (intval(sc) >= 300) && (intval(sc) < 400); } public boolean is_error(Object sc) { return (intval(sc) >= 400) && (intval(sc) < 600); } public boolean is_client_error(Object sc) { return (intval(sc) >= 400) && (intval(sc) < 500); } public boolean is_server_error(Object sc) { return (intval(sc) >= 500) && (intval(sc) < 600); } public int parse_w3cdtf(String date_str) { String pat = null; Array<Object> match = new Array<Object>(); int epoch = 0; int offset = 0; int offset_secs = 0; // regex to match wc3dtf pat = "/(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(:(\\d{2}))?(?:([-+])(\\d{2}):?(\\d{2})|(Z))?/"; if (QRegExPerl.preg_match(pat, date_str, match)) { new ListAssigner<Object>() { public Array<Object> doAssign(Array<Object> srcArray) { if (strictEqual(srcArray, null)) { return null; } parse_w3cdtf_year = intval(srcArray.getValue(0)); parse_w3cdtf_month = intval(srcArray.getValue(1)); parse_w3cdtf_day = intval(srcArray.getValue(2)); parse_w3cdtf_hours = intval(srcArray.getValue(3)); parse_w3cdtf_minutes = intval(srcArray.getValue(4)); parse_w3cdtf_seconds = intval(srcArray.getValue(5)); return srcArray; } }.doAssign( new Array<Object>(new ArrayEntry<Object>(match.getValue(1)), new ArrayEntry<Object>(match.getValue(2)), new ArrayEntry<Object>(match.getValue(3)), new ArrayEntry<Object>(match.getValue(4)), new ArrayEntry<Object>(match.getValue(5)), new ArrayEntry<Object>(match.getValue(7)))); // calc epoch for current date assuming GMT epoch = DateTime.gmmktime(parse_w3cdtf_hours, parse_w3cdtf_minutes, parse_w3cdtf_seconds, parse_w3cdtf_month, parse_w3cdtf_day, parse_w3cdtf_year); offset = 0; if (equal(match.getValue(11), "Z")) { // zulu time, aka GMT } else { new ListAssigner<Object>() { public Array<Object> doAssign(Array<Object> srcArray) { if (strictEqual(srcArray, null)) { return null; } parse_w3cdtf_tz_mod = srcArray.getValue(0); parse_w3cdtf_tz_hour = intval(srcArray.getValue(1)); parse_w3cdtf_tz_min = intval(srcArray.getValue(2)); return srcArray; } }.doAssign(new Array<Object>(new ArrayEntry<Object>(match.getValue(8)), new ArrayEntry<Object>(match.getValue(9)), new ArrayEntry<Object>(match.getValue(10)))); // zero out the variables if (!booleanval(parse_w3cdtf_tz_hour)) { parse_w3cdtf_tz_hour = 0; } if (!booleanval(parse_w3cdtf_tz_min)) { parse_w3cdtf_tz_min = 0; } offset_secs = ((parse_w3cdtf_tz_hour * 60) + parse_w3cdtf_tz_min) * 60; // is timezone ahead of GMT? then subtract offset // if (equal(parse_w3cdtf_tz_mod, "+")) { offset_secs = offset_secs * (-1); } offset = offset_secs; } epoch = epoch + offset; return epoch; } else { return -1; } } public void wp_rss(String url, int num_items) { MagpieRSS rss = null; Array<Object> item = new Array<Object>(); if (booleanval(rss = fetch_rss(url))) { echo(gVars.webEnv, "<ul>"); if (!strictEqual(num_items, -1)) { rss.items = Array.array_slice(rss.items, 0, num_items); } for (Map.Entry javaEntry589 : rss.items.entrySet()) { item = (Array<Object>) javaEntry589.getValue(); QStrings.printf( gVars.webEnv, "<li><a href=\"%1$s\" title=\"%2$s\">%3$s</a></li>", getIncluded(FormattingPage.class, gVars, gConsts).clean_url(strval(item.getValue("link")), null, "display"), getIncluded(FormattingPage.class, gVars, gConsts).attribute_escape(Strings.strip_tags(strval(item.getValue("description")))), Strings.htmlentities(strval(item.getValue("title")))); } echo(gVars.webEnv, "</ul>"); } else { getIncluded(L10nPage.class, gVars, gConsts)._e("An error has occurred, which probably means the feed is down. Try again later.", "default"); } } public boolean get_rss(String url, int num_items) { // Like get posts, but for RSS MagpieRSS rss = null; Array<Object> item = new Array<Object>(); rss = fetch_rss(url); if (booleanval(rss)) { rss.items = Array.array_slice(rss.items, 0, num_items); for (Map.Entry javaEntry590 : rss.items.entrySet()) { item = (Array<Object>) javaEntry590.getValue(); echo(gVars.webEnv, "<li>\n"); echo(gVars.webEnv, "<a href=\'" + strval(item.getValue("link")) + "\' title=\'" + strval(item.getValue("description")) + "\'>"); echo(gVars.webEnv, Strings.htmlentities(strval(item.getValue("title")))); echo(gVars.webEnv, "</a><br />\n"); echo(gVars.webEnv, "</li>\n"); } } else { return false; } return false; } public Object generateContent(PhpWebEnvironment webEnv) throws IOException, ServletException { /* Start of block */ super.startBlock("__wp_includes_rss_block1"); gVars.webEnv = webEnv; /** * MagpieRSS: a simple RSS integration tool * * A compiled file for RSS syndication * * @author Kellan Elliott-McCrea <kellan@protest.net> * @version 0.51 * @license GPL * * @package External * @subpackage MagpieRSS */ /* * Hook to use another RSS object instead of MagpieRSS */ getIncluded(PluginPage.class, gVars, gConsts).do_action("load_feed_engine", ""); gConsts.setRSS("RSS"); gConsts.setATOM("Atom"); gConsts.setMAGPIE_USER_AGENT("nWordPress/" + gVars.wp_version); return DEFAULT_VAL; } }