Esempio n. 1
0
/**
 * Convenience for those who prefer "SELECT * FROM textpattern"
 *
 * @param array $rs An assoc w/ one article's data from the DB
 */
function article_format_info($rs)
{
    $rs['uPosted'] = ($unix_ts = @strtotime($rs['Posted'])) > 0 ? $unix_ts : NULLDATETIME;
    $rs['uLastMod'] = ($unix_ts = @strtotime($rs['LastMod'])) > 0 ? $unix_ts : NULLDATETIME;
    $rs['uExpires'] = ($unix_ts = @strtotime($rs['Expires'])) > 0 ? $unix_ts : NULLDATETIME;
    populateArticleData($rs);
}
Esempio n. 2
0
function discuss($id)
{
    $rs = safe_row('*, unix_timestamp(Posted) as uPosted, unix_timestamp(LastMod) as uLastMod, unix_timestamp(Expires) as uExpires', 'textpattern', 'ID=' . intval($id) . ' and Status >= 4');
    if ($rs) {
        populateArticleData($rs);
        $result = parse_form('comments_display');
        return $result;
    }
    return '';
}
Esempio n. 3
0
function discuss($id)
{
    $rs = safe_row('*, unix_timestamp(Posted) as uPosted', 'textpattern', "ID='" . doSlash($id) . "' and Status >= 4");
    if ($rs) {
        populateArticleData($rs);
        if (ps('preview')) {
            $GLOBALS['comment_preview'] = 1;
        }
        $result = parse(fetch_form('comments_display'));
        unset($GLOBALS['comment_preview']);
        return $result;
    }
    return '';
}
Esempio n. 4
0
/**
 * Generates and outputs an Atom feed.
 *
 * This function can only be called once on a page. It outputs an Atom feed
 * based on the requested URL parameters. Accepts HTTP GET parameters 'limit',
 * 'area', 'section' and 'category'.
 */
function atom()
{
    global $thisarticle, $prefs;
    set_error_handler('feedErrorHandler');
    ob_clean();
    extract($prefs);
    $last = fetch("UNIX_TIMESTAMP(val)", 'txp_prefs', 'name', 'lastmod');
    extract(doSlash(gpsa(array('limit', 'area'))));
    // Build filter criteria from a comma-separated list of sections
    // and categories.
    $feed_filter_limit = get_pref('feed_filter_limit', 10);
    $section = gps('section');
    $category = gps('category');
    if (!is_scalar($section) || !is_scalar($category)) {
        txp_die('Not Found', 404);
    }
    $section = $section ? array_slice(do_list_unique($section), 0, $feed_filter_limit) : array();
    $category = $category ? array_slice(do_list_unique($category), 0, $feed_filter_limit) : array();
    $st = array();
    foreach ($section as $s) {
        $st[] = fetch_section_title($s);
    }
    $ct = array();
    foreach ($category as $c) {
        $ct[] = fetch_category_title($c);
    }
    $sitename .= $section ? ' - ' . join(' - ', $st) : '';
    $sitename .= $category ? ' - ' . join(' - ', $ct) : '';
    $pub = safe_row("RealName, email", 'txp_users', "privs = 1");
    // Feed header.
    $out[] = tag(htmlspecialchars($sitename), 'title', t_text);
    $out[] = tag(htmlspecialchars($site_slogan), 'subtitle', t_text);
    $out[] = '<link' . r_relself . ' href="' . pagelinkurl(array('atom' => 1, 'area' => $area, 'section' => $section, 'category' => $category, 'limit' => $limit)) . '" />';
    $out[] = '<link' . r_relalt . t_texthtml . ' href="' . hu . '" />';
    // Atom feeds with mail or domain name.
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    $out[] = tag('tag:' . $mail_or_domain . ',' . $blog_time_uid . ':' . $blog_uid . ($section ? '/' . join(',', $section) : '') . ($category ? '/' . join(',', $category) : ''), 'id');
    $out[] = tag('Textpattern', 'generator', ' uri="http://textpattern.com/" version="' . $version . '"');
    $out[] = tag(safe_strftime("w3cdtf", $last), 'updated');
    $auth[] = tag($pub['RealName'], 'name');
    $auth[] = $include_email_atom ? tag(eE($pub['email']), 'email') : '';
    $auth[] = tag(hu, 'uri');
    $out[] = tag(n . t . t . join(n . t . t, $auth) . n, 'author');
    $out[] = callback_event('atom_head');
    // Feed items.
    $articles = array();
    $section = doSlash($section);
    $category = doSlash($category);
    if (!$area or $area == 'article') {
        $sfilter = !empty($section) ? "AND Section IN ('" . join("','", $section) . "')" : '';
        $cfilter = !empty($category) ? "AND (Category1 IN ('" . join("','", $category) . "') OR Category2 IN ('" . join("','", $category) . "'))" : '';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $frs = safe_column("name", 'txp_section', "in_rss != '1'");
        $query = array();
        foreach ($frs as $f) {
            $query[] = "AND Section != '" . doSlash($f) . "'";
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $expired = $publish_expired_articles ? " " : " AND (" . now('expires') . " <= Expires OR Expires = " . NULLDATETIME . ") ";
        $rs = safe_rows_start("*,\n            ID AS thisid,\n            UNIX_TIMESTAMP(Posted) AS uPosted,\n            UNIX_TIMESTAMP(Expires) AS uExpires,\n            UNIX_TIMESTAMP(LastMod) AS uLastMod", 'textpattern', "Status = 4 AND Posted <= " . now('posted') . $expired . join(' ', $query) . "ORDER BY Posted DESC LIMIT {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event('atom_entry');
                $e = array();
                $a['posted'] = $uPosted;
                $a['expires'] = $uExpires;
                if ($show_comment_count_in_feed) {
                    $count = $comments_count > 0 ? ' [' . $comments_count . ']' : '';
                } else {
                    $count = '';
                }
                $thisauthor = get_author_name($AuthorID);
                $e['thisauthor'] = tag(n . t . t . t . tag(htmlspecialchars($thisauthor), 'name') . n . t . t, 'author');
                $e['issued'] = tag(safe_strftime('w3cdtf', $uPosted), 'published');
                $e['modified'] = tag(safe_strftime('w3cdtf', $uLastMod), 'updated');
                $escaped_title = htmlspecialchars($Title);
                $e['title'] = tag($escaped_title . $count, 'title', t_html);
                $permlink = permlinkurl($a);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $permlink . '" />';
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'id');
                $e['category1'] = trim($Category1) ? '<category term="' . htmlspecialchars($Category1) . '" />' : '';
                $e['category2'] = trim($Category2) ? '<category term="' . htmlspecialchars($Category2) . '" />' : '';
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    // Short feed: use body as summary if there's no excerpt.
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if (trim($content)) {
                    $e['content'] = tag(n . escape_cdata($content) . n, 'content', t_html);
                }
                if (trim($summary)) {
                    $e['summary'] = tag(n . escape_cdata($summary) . n, 'summary', t_html);
                }
                $articles[$ID] = tag(n . t . t . join(n . t . t, $e) . n . $cb, 'entry');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uLastMod;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category in ('" . join("','", $category) . "')" : '1';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $rs = safe_rows_start("*", 'txp_link', "{$cfilter} ORDER BY date DESC, id DESC LIMIT {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $e['title'] = tag(htmlspecialchars($linkname), 'title', t_html);
                $e['content'] = tag(n . htmlspecialchars($description) . n, 'content', t_html);
                $url = preg_replace("/^\\/(.*)/", "https?://{$siteurl}/\$1", $url);
                $url = preg_replace("/&((?U).*)=/", "&amp;\\1=", $url);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $url . '" />';
                $e['issued'] = tag(safe_strftime('w3cdtf', strtotime($date)), 'published');
                $e['modified'] = tag(gmdate('Y-m-d\\TH:i:s\\Z', strtotime($date)), 'updated');
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . safe_strftime('%Y-%m-%d', strtotime($date)) . ':' . $blog_uid . '/' . $id, 'id');
                $articles[$id] = tag(n . t . t . join(n . t . t, $e) . n, 'entry');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!$articles) {
        if ($section) {
            if (safe_field("name", 'txp_section', "name IN ('" . join("','", $section) . "')") == false) {
                txp_die(gTxt('404_not_found'), '404');
            }
        } elseif ($category) {
            switch ($area) {
                case 'link':
                    if (safe_field("id", 'txp_category', "name = '{$category}' AND type = 'link'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
                case 'article':
                default:
                    if (safe_field("id", 'txp_category', "name IN ('" . join("','", $category) . "') AND type = 'article'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
            }
        }
    } else {
        // Turn on compression if we aren't using it already.
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            // Make sure notices/warnings/errors don't fudge up the feed when
            // compression is used.
            $buf = '';
            while ($b = @ob_get_clean()) {
                $buf .= $b;
            }
            @ob_start('ob_gzhandler');
            echo $buf;
        }
        handle_lastmod();
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        $imsd = $hims ? strtotime($hims) : 0;
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id])) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } elseif (isset($cut_etag)) {
            header("Vary: If-None-Match");
        } elseif (isset($cut_time)) {
            header("Vary: If-Modified-Since");
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            txp_status_header('304 Not Modified');
            exit(0);
        }
        if ($etag) {
            header('ETag: "' . $etag . '"');
        }
        if ($cutarticles) {
            // header("HTTP/1.1 226 IM Used");
            // This should be used as opposed to 200, but Apache doesn't like it.
            // http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the
            // status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
    }
    $out = array_merge($out, $articles);
    header('Content-type: application/atom+xml; charset=utf-8');
    return chr(60) . '?xml version="1.0" encoding="UTF-8"?' . chr(62) . n . '<feed xml:lang="' . txpspecialchars($language) . '" xmlns="http://www.w3.org/2005/Atom">' . join(n, $out) . '</feed>';
}
Esempio n. 5
0
function doArticle($atts, $thing = null)
{
    global $pretext, $prefs, $thisarticle;
    extract($prefs);
    extract($pretext);
    extract(gpsa(array('parentid', 'preview')));
    $theAtts = lAtts(array('allowoverride' => '1', 'form' => 'default', 'status' => STATUS_LIVE, 'pgonly' => 0), $atts, 0);
    extract($theAtts);
    // Save *all* atts to get hold of the current article filter criteria.
    filterAtts($atts);
    // No output required.
    if ($pgonly) {
        return '';
    }
    // If a form is specified, $thing is for doArticles() - hence ignore
    // $thing here.
    if (!empty($atts['form'])) {
        $thing = '';
    }
    if ($status) {
        $status = in_array(strtolower($status), array('sticky', STATUS_STICKY)) ? STATUS_STICKY : STATUS_LIVE;
    }
    if (empty($thisarticle) or $thisarticle['thisid'] != $id) {
        $id = assert_int($id);
        $thisarticle = null;
        $q_status = $status ? "AND Status = " . intval($status) : "AND Status IN (" . STATUS_LIVE . "," . STATUS_STICKY . ")";
        $rs = safe_row("*, UNIX_TIMESTAMP(Posted) AS uPosted, UNIX_TIMESTAMP(Expires) AS uExpires, UNIX_TIMESTAMP(LastMod) AS uLastMod", 'textpattern', "ID = {$id} {$q_status} LIMIT 1");
        if ($rs) {
            extract($rs);
            populateArticleData($rs);
        }
    }
    if (!empty($thisarticle) and ($thisarticle['status'] == $status or gps('txpreview'))) {
        extract($thisarticle);
        $thisarticle['is_first'] = 1;
        $thisarticle['is_last'] = 1;
        if ($allowoverride and $override_form) {
            $article = parse_form($override_form);
        } else {
            $article = $thing ? parse($thing) : parse_form($form);
        }
        if ($use_comments and $comments_auto_append) {
            $article .= parse_form('comments_display');
        }
        unset($GLOBALS['thisarticle']);
        return $article;
    }
}
Esempio n. 6
0
function doArticle($atts, $thing = NULL)
{
    global $pretext, $prefs, $thisarticle;
    extract($prefs);
    extract($pretext);
    extract(gpsa(array('parentid', 'preview')));
    extract(lAtts(array('allowoverride' => '1', 'form' => 'default', 'status' => '4'), $atts, 0));
    // if a form is specified, $thing is for doArticles() - hence ignore $thing here.
    if (!empty($atts['form'])) {
        $thing = '';
    }
    if ($status) {
        $status = in_array(strtolower($status), array('sticky', '5')) ? 5 : 4;
    }
    if (empty($thisarticle) or $thisarticle['thisid'] != $id) {
        $thisarticle = NULL;
        $q_status = $status ? 'and Status = ' . intval($status) : 'and Status in (4,5)';
        $rs = safe_row("*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod", "textpattern", 'ID = ' . intval($id) . " {$q_status} limit 1");
        if ($rs) {
            extract($rs);
            populateArticleData($rs);
        }
    }
    if (!empty($thisarticle) and ($thisarticle['status'] == $status or gps('txpreview'))) {
        extract($thisarticle);
        $thisarticle['is_first'] = 1;
        $thisarticle['is_last'] = 1;
        if ($allowoverride and $override_form) {
            $article = parse_form($override_form);
        } else {
            $article = $thing ? parse($thing) : parse_form($form);
        }
        if ($use_comments and $comments_auto_append) {
            $article .= parse_form('comments_display');
        }
        unset($GLOBALS['thisarticle']);
        return $article;
    }
}
Esempio n. 7
0
function popup_comments($atts, $thing = null)
{
    extract(lAtts(array('form' => 'comments_display'), $atts));
    $rs = safe_row("*, UNIX_TIMESTAMP(Posted) AS uPosted, UNIX_TIMESTAMP(LastMod) AS uLastMod, UNIX_TIMESTAMP(Expires) AS uExpires", 'textpattern', "ID=" . intval(gps('parentid')) . " AND Status >= 4");
    if ($rs) {
        populateArticleData($rs);
        return $thing === null ? parse_form($form) : parse($thing);
    }
    return '';
}
Esempio n. 8
0
function related_articles($atts, $thing = NULL)
{
    global $thisarticle, $prefs;
    assert_article();
    extract(lAtts(array('break' => br, 'class' => __FUNCTION__, 'form' => '', 'label' => '', 'labeltag' => '', 'limit' => 10, 'match' => 'Category1,Category2', 'no_widow' => @$prefs['title_no_widow'], 'section' => '', 'sort' => 'Posted desc', 'wraptag' => ''), $atts));
    if (empty($thisarticle['category1']) and empty($thisarticle['category2'])) {
        return;
    }
    $match = do_list($match);
    if (!in_array('Category1', $match) and !in_array('Category2', $match)) {
        return;
    }
    $id = $thisarticle['thisid'];
    $cats = array();
    if ($thisarticle['category1']) {
        $cats[] = doSlash($thisarticle['category1']);
    }
    if ($thisarticle['category2']) {
        $cats[] = doSlash($thisarticle['category2']);
    }
    $cats = join("','", $cats);
    $categories = array();
    if (in_array('Category1', $match)) {
        $categories[] = "Category1 in('{$cats}')";
    }
    if (in_array('Category2', $match)) {
        $categories[] = "Category2 in('{$cats}')";
    }
    $categories = 'and (' . join(' or ', $categories) . ')';
    $section = $section ? " and Section IN ('" . join("','", doSlash(do_list($section))) . "')" : '';
    $expired = $prefs['publish_expired_articles'] ? '' : ' and (now() <= Expires or Expires = ' . NULLDATETIME . ') ';
    $rs = safe_rows_start('*, unix_timestamp(Posted) as posted, unix_timestamp(LastMod) as uLastMod, unix_timestamp(Expires) as uExpires', 'textpattern', 'ID != ' . intval($id) . " and Status = 4 {$expired}  and Posted <= now() {$categories} {$section} order by " . doSlash($sort) . ' limit 0,' . intval($limit));
    if ($rs) {
        $out = array();
        $old_article = $thisarticle;
        while ($a = nextRow($rs)) {
            $a['Title'] = $no_widow ? noWidow(escape_title($a['Title'])) : escape_title($a['Title']);
            $a['uPosted'] = $a['posted'];
            // populateArticleData() and permlinkurl() assume quite a bunch of posting dates...
            if (empty($form) && empty($thing)) {
                $out[] = href($a['Title'], permlinkurl($a));
            } else {
                populateArticleData($a);
                $out[] = $thing ? parse($thing) : parse_form($form);
            }
        }
        $thisarticle = $old_article;
        if ($out) {
            return doLabel($label, $labeltag) . doWrap($out, $wraptag, $break, $class);
        }
    }
    return '';
}
Esempio n. 9
0
function doArticle($atts)
{
    global $pretext, $prefs;
    extract($prefs);
    extract($pretext);
    $preview = ps('preview');
    $parentid = ps('parentid');
    extract(lAtts(array('form' => 'default', 'status' => ''), $atts));
    if ($status and !is_numeric($status)) {
        $status = getStatusNum($status);
    }
    $q_status = $status ? "and Status='" . doSlash($status) . "'" : 'and Status in (4,5)';
    $rs = safe_row("*, unix_timestamp(Posted) as uPosted", "textpattern", "ID='" . intval($id) . "' {$q_status} limit 1");
    if ($rs) {
        extract($rs);
        populateArticleData($rs);
        $GLOBALS['thisarticle']['is_first'] = 1;
        $GLOBALS['thisarticle']['is_last'] = 1;
        // define the article form
        $article = fetch_form($override_form ? $override_form : $form);
        if ($preview && $parentid) {
            $article = '<txp:comments_preview bc="1" id="' . $parentid . '" />' . $article;
        }
        $article = parse($article);
        if ($use_comments and $comments_auto_append) {
            $f = fetch_form('comments_display');
            $article .= parse($f);
        }
        unset($GLOBALS['thisarticle']);
        return $article;
    }
}
Esempio n. 10
0
function atom()
{
    global $thisarticle;
    extract($GLOBALS['prefs']);
    define("textplain", ' type="text/plain"');
    define("texthtml", ' type="text/html"');
    define("relalt", ' rel="alternate"');
    define('appxhtml', ' type="application/xhtml+xml"');
    define("divxhtml", '<div xmlns="http://www.w3.org/1999/xhtml">');
    $area = doSlash(gps('area'));
    extract(doSlash(gpsa(array('category', 'section', 'limit'))));
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    $sitename .= $section ? ' - ' . $section : '';
    $sitename .= $category ? ' - ' . $category : '';
    $pub = safe_row("RealName, email", "txp_users", "privs=1");
    $out[] = tag($sitename, 'title', textplain);
    $out[] = tag($site_slogan, 'tagline', textplain);
    $out[] = '<link' . relalt . texthtml . ' href="' . hu . '" />';
    $articles = array();
    //Atom feeds with mail or domain name
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    $out[] = tag('tag:' . $mail_or_domain . ',' . $blog_time_uid . ':' . $blog_uid . ($section ? '/' . $section : '') . ($category ? '/' . $category : ''), 'id');
    $out[] = tag('Textpattern', 'generator', ' url="http://textpattern.com" version="' . $version . '"');
    $out[] = tag(date("Y-m-d\\TH:i:s\\Z", $last), 'modified');
    $auth[] = tag($pub['RealName'], 'name');
    $auth[] = $include_email_atom ? tag(eE($pub['email']), 'email') : '';
    $auth[] = tag(hu, 'url');
    $out[] = tag(n . t . t . join(n . t . t, $auth) . n, 'author');
    if (!$area or $area == 'article') {
        $sfilter = $section ? "and Section = '" . $section . "'" : '';
        $cfilter = $category ? "and (Category1='" . $category . "' or Category2='" . $category . "')" : '';
        $limit = $limit ? $limit : '5';
        $frs = safe_column("name", "txp_section", "in_rss != '1'");
        foreach ($frs as $f) {
            $query[] = "and Section != '" . $f . "'";
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $rs = safe_rows_start("*, \n\t\t\t\tID as thisid, \n\t\t\t\tunix_timestamp(Posted) as uPosted,\n\t\t\t\tunix_timestamp(LastMod) as uLastMod", "textpattern", "Status=4 and Posted <= now() " . join(' ', $query) . "order by Posted desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $a['posted'] = $uPosted;
                if ($show_comment_count_in_feed) {
                    $dc = getCount('txp_discuss', "parentid={$ID} and visible=1");
                    $count = $dc > 0 ? ' [' . $dc . ']' : '';
                } else {
                    $count = '';
                }
                $thisauthor = safe_field("RealName", "txp_users", "name='{$AuthorID}'");
                $e['thisauthor'] = tag(n . t . t . t . tag(htmlspecialchars($thisauthor), 'name') . n . t . t, 'author');
                $e['issued'] = tag(gmdate("Y-m-d\\TH:i:s\\Z", $uPosted), 'issued');
                $e['modified'] = tag(gmdate("Y-m-d\\TH:i:s\\Z", $uLastMod), 'modified');
                $escaped_title = safe_hed($Title);
                $escaped_title = preg_replace("/&(?![#a-z0-9]+;)/i", '&amp;', $escaped_title);
                $escaped_title = str_replace('<', '&lt;', $escaped_title);
                $escaped_title = str_replace('>', '&gt;', $escaped_title);
                $e['title'] = tag($escaped_title . $count, 'title');
                $uTitle = $url_title ? $url_title : stripSpace($Title);
                $uTitle = htmlspecialchars($uTitle, ENT_NOQUOTES);
                $permlink = permlinkurl($a);
                $e['link'] = '<link' . relalt . texthtml . ' href="' . $permlink . '" />';
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'id');
                $e['subject'] = tag(htmlspecialchars($Category1), 'dc:subject');
                // pull Body or Excerpt?
                $Body = !$syndicate_body_or_excerpt ? $thisarticle['body'] : $thisarticle['excerpt'];
                // if Excerpt is empty, switch back to Body_html
                $Body = !trim($Body) ? $thisarticle['body'] : $Body;
                // fix relative urls
                $Body = str_replace('href="/', 'href="' . hu, $Body);
                $Body = preg_replace("/href=\\\"#(.*)\"/", "href=\"" . permlinkurl($a) . "#\\1\"", $Body);
                $Body = safe_hed($Body);
                // encode and entify
                $Body = preg_replace(array('/</', '/>/', "/'/", '/"/'), array('&#60;', '&#62;', '&#039;', '&#34;'), $Body);
                // encode bare ampersands
                $Body = preg_replace("/&(?![#0-9]+;|\\w+;)/i", '&amp;', $Body);
                $e['content'] = tag(n . $Body . n, 'content', ' type="text/html" mode="escaped"');
                $articles[$ID] = tag(n . t . t . join(n . t . t, $e) . n, 'entry');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uLastMod;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category='{$category}'" : '1';
        $limit = $limit ? $limit : 15;
        $rs = safe_rows_start("*", "txp_link", "{$cfilter} order by date desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $e['title'] = tag(doSpecial($linkname), 'title');
                $content = utf8_encode(htmlspecialchars($description));
                $e['content'] = tag(n . $description . n, 'content', ' type="text/html" mode="escaped"');
                $url = preg_replace("/^\\/(.*)/", "http://{$siteurl}/\$1", $url);
                $url = preg_replace("/&((?U).*)=/", "&amp;\\1=", $url);
                $e['link'] = '<link' . relalt . texthtml . ' href="' . $url . '" />';
                $e['issued'] = tag(gmdate("Y-m-d\\TH:i:s\\Z", $date), 'issued');
                $e['modified'] = tag(gmdate("Y-m-d\\TH:i:s\\Z", $date), 'modified');
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $id, 'id');
                $articles[$id] = tag(n . t . t . join(n . t . t, $e) . n, 'entry');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!empty($articles)) {
        //turn on compression if we aren't using it already
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            ob_start("ob_gzhandler");
        }
        $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
        $last = gmdate("D, d M Y H:i:s \\G\\M\\T", $last);
        header("Last-Modified: {$last}");
        $expires = gmdate('D, d M Y H:i:s \\G\\M\\T', time() + 3600 * 1);
        header("Expires: {$expires}");
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        if ($hims == $last) {
            header("HTTP/1.1 304 Not Modified");
            exit;
        }
        $imsd = @strtotime($hims);
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id])) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } else {
            if (isset($cut_etag)) {
                header("Vary: If-None-Match");
            } else {
                if (isset($cut_time)) {
                    header("Vary: If-Modified-Since");
                }
            }
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            header("HTTP/1.1 304 Not Modified");
            exit;
        }
        if ($etag) {
            header('ETag: "' . $etag . '"');
        }
        if ($cutarticles) {
            //header("HTTP/1.1 226 IM Used");
            //This should be used as opposed to 200, but Apache doesn't like it.
            //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
        $out = array_merge($out, $articles);
        ob_start();
        header('Content-type: application/atom+xml; charset=utf-8');
        return chr(60) . '?xml version="1.0" encoding="UTF-8"?' . chr(62) . n . '<feed version="0.3" xml:lang="' . $language . '" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">' . join(n, $out) . '</feed>';
    }
}
Esempio n. 11
0
function doHomeArticles($atts, $thing = NULL)
{
    global $pretext, $prefs;
    extract($pretext);
    extract($prefs);
    $customFields = getCustomFields();
    $customlAtts = array_null(array_flip($customFields));
    //getting attributes
    $theAtts = lAtts(array('form' => 'default', 'listform' => '', 'searchform' => '', 'limit' => 10, 'category' => '', 'section' => '', 'excerpted' => '', 'author' => '', 'sort' => '', 'month' => '', 'keywords' => '', 'frontpage' => '', 'time' => 'past', 'pgonly' => 0, 'searchall' => 1, 'allowoverride' => true, 'offset' => 0, 'wraptag' => '', 'break' => '', 'label' => '', 'labeltag' => '', 'class' => '') + $customlAtts, $atts);
    $theAtts['category'] = $c ? $c : '';
    $theAtts['section'] = $s && $s != 'default' && $s != 'home' ? $s : '';
    $theAtts['author'] = !empty($author) ? $author : '';
    $theAtts['month'] = !empty($month) ? $month : '';
    $theAtts['frontpage'] = $s && $s == 'home' ? true : false;
    $theAtts['excerpted'] = '';
    extract($theAtts);
    // if a listform is specified, $thing is for doArticle() - hence ignore here.
    if (!empty($listform)) {
        $thing = '';
    }
    $pageby = empty($pageby) ? $limit : $pageby;
    $match = $search = '';
    if (!$sort) {
        $sort = 'Posted desc';
    }
    //Building query parts
    $frontpage = filterFrontPage();
    $category = join("','", doSlash(do_list($category)));
    $category = !$category ? '' : " and (Category1 IN ('" . $category . "') or Category2 IN ('" . $category . "'))";
    $section = !$section ? '' : " and Section IN ('" . join("','", doSlash(do_list($section))) . "')";
    $excerpted = $excerpted == 'y' ? " and Excerpt !=''" : '';
    $author = !$author ? '' : " and AuthorID IN ('" . join("','", doSlash(do_list($author))) . "')";
    $month = !$month ? '' : " and Posted like '" . doSlash($month) . "%'";
    $id = !$id ? '' : " and ID IN (" . join(',', array_map('intval', do_list($id))) . ")";
    switch ($time) {
        case 'any':
            $time = "";
            break;
        case 'future':
            $time = " and Posted > now()";
            break;
        default:
            $time = " and Posted <= now()";
    }
    if (!$publish_expired_articles) {
        $time .= " and (now() <= Expires or Expires = " . NULLDATETIME . ")";
    }
    $custom = '';
    if ($customFields) {
        foreach ($customFields as $cField) {
            if (isset($atts[$cField])) {
                $customPairs[$cField] = $atts[$cField];
            }
        }
        if (!empty($customPairs)) {
            $custom = buildCustomSql($customFields, $customPairs);
        }
    }
    $statusq = ' and Status = 5';
    $where = "1=1" . $statusq . $time . $search . $category . $section . $excerpted . $month . $author . $keywords . $custom . $frontpage;
    $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod" . $match, 'textpattern', $where . ' order by ' . doSlash($sort) . ' limit 0' . intval($limit));
    // get the form name
    $fname = $listform ? $listform : $form;
    if ($rs) {
        $count = 0;
        $last = numRows($rs);
        $articles = array();
        while ($a = nextRow($rs)) {
            ++$count;
            populateArticleData($a);
            global $thisarticle, $uPosted, $limit;
            $thisarticle['is_first'] = $count == 1;
            $thisarticle['is_last'] = $count == $last;
            if (@constant('txpinterface') === 'admin' and gps('Form')) {
                $articles[] = parse(gps('Form'));
            } elseif ($allowoverride and $a['override_form']) {
                $articles[] = parse_form($a['override_form']);
            } else {
                $articles[] = $thing ? parse($thing) : parse_form($fname);
            }
            // sending these to paging_link(); Required?
            $uPosted = $a['uPosted'];
            unset($GLOBALS['thisarticle']);
        }
        return doLabel($label, $labeltag) . doWrap($articles, $wraptag, $break, $class);
    }
}
 function _textpattern()
 {
     global $plugins_ver, $pretext, $prefs, $plugin_callback;
     $this->debug('Plugin: ' . $this->plugin_name . ' - ' . $plugins_ver[$this->plugin_name]);
     $this->debug('Function: ' . __FUNCTION__ . '()');
     // URI
     $req = $pretext['req'];
     $req = preg_replace('%\\?[^\\/]+$%', '', $req);
     $this->debug('Request URI: ' . $req);
     $uri = explode('/', trim($req, '/'));
     // The number of components comes in useful when determining the best partial match.
     $uri_component_count = count($uri);
     // Permanent links
     $permlinks = $this->get_all_permlinks(1);
     // Force Textpattern and tags to use messy URLs - these are easier to
     // find in regex
     $this->set_permlink_mode();
     if (count($permlinks)) {
         // We also want to match the front page of the site (for page numbers / feeds etc..).
         // Add a permlinks rule which will do that.
         $permlinks['default'] = array('components' => array(), 'settings' => array('pl_name' => 'gbp_permanent_links_default', 'pl_precedence' => '', 'pl_preview' => '/', 'con_section' => '', 'con_category' => '', 'des_section' => '', 'des_category' => '', 'des_permlink' => '', 'des_feed' => '', 'des_location' => '', 'des_page' => ''));
         // Extend the pretext_replacement scope outside the foreach permlink loop
         $pretext_replacement = NULL;
         foreach ($permlinks as $id => $pl) {
             // Extract the permlink settings
             $pl_settings = $pl['settings'];
             extract($pl_settings);
             $this->debug('Permlink name: ' . $pl_name);
             $this->debug('Permlink id: ' . $id);
             $this->debug('Preview: ' . $pl_preview);
             $pl_components = $pl['components'];
             // URI components
             $uri_components = $uri;
             $this->debug('PL component count: ' . count($pl_components));
             $this->debug('URL component count: ' . count($uri_components));
             $date = false;
             $title_page_feed = false;
             foreach ($pl_components as $pl_c) {
                 // Are we expecting a date component? If so the number of pl and uri components won't match
                 if ($pl_c['type'] == 'date') {
                     $date = true;
                 } else {
                     if (in_array($pl_c['type'], array('title', 'page', 'feed'))) {
                         $title_page_feed = true;
                     }
                 }
             }
             if (!$title_page_feed) {
                 // If there isn't a title, page or feed component then append a special type for cleaver partial matching
                 $pl_components[] = array('type' => 'title_page_feed', 'prefix' => '', 'suffix' => '', 'regex' => '', 'text' => '');
             }
             // Exit early if there are more URL components than PL components,
             // taking into account whether there is a data component
             if (!$uri_components[0] || count($uri_components) > count($pl_components) + ($date ? 2 : 0)) {
                 $this->debug('More URL components than PL components');
                 continue;
             }
             // Reset pretext_replacement as we are about to start another comparison
             $pretext_replacement = array('permlink_id' => $id);
             // Reset the article context string
             $context = array();
             unset($context_str);
             if (!empty($des_section)) {
                 $context[] = "`Section` = '{$des_section}'";
             }
             if (!empty($des_category)) {
                 $context[] = "(`Category1` = '{$des_category}' OR `Category2` = '{$des_category}')";
             }
             $context_str = count($context) > 0 ? 'and ' . join(' and ', $context) : '';
             // Assume there is no match
             $partial_match = false;
             $cleaver_partial_match = false;
             // Loop through the permlink components
             foreach ($pl_components as $pl_c_index => $pl_c) {
                 // Assume there is no match
                 $match = false;
                 // Check to see if there are still URI components to be checked.
                 if (count($uri_components)) {
                     // Get the next component.
                     $uri_c = array_shift($uri_components);
                 } else {
                     if (!$title_page_feed && count($pl_components) - 1 == $uri_component_count) {
                         // If we appended a title_page_feed component earlier and permlink and URI components
                         // counts are equal, we must of finished checking this permlink, and it matches so break.
                         $match = true;
                         break;
                     } else {
                         // If there are no more URI components then we have a partial match.
                         // Store the partial match data unless there has been a preceding permlink with the
                         // same number of components, as permlink have already been sorted by precedence.
                         if (!array_key_exists($uri_component_count, $this->partial_matches)) {
                             $this->partial_matches[$uri_component_count] = $pretext_replacement;
                         }
                         // Unset pretext_replacement as changes could of been made in a preceding component
                         unset($pretext_replacement);
                         // Break early form the foreach permlink components loop.
                         $partial_match = true;
                         break;
                     }
                 }
                 // Extract the permlink components.
                 extract($pl_c);
                 // If it's a date, grab and combine the next two URI components.
                 if ($type == 'date') {
                     $uri_c .= '/' . array_shift($uri_components) . '/' . array_shift($uri_components);
                 }
                 // Decode the URL
                 $uri_c = urldecode($uri_c);
                 // Always check the type unless the prefix or suffix aren't there
                 $check_type = true;
                 // Check prefix
                 if ($prefix && $this->pref('show_prefix')) {
                     $sanitized_prefix = urldecode($this->encode_url($prefix));
                     if (($pos = strpos($uri_c, $sanitized_prefix)) === false || $pos != 0) {
                         $check_type = false;
                         $this->debug('Can\'t find prefix: ' . $prefix);
                     } else {
                         // Check passed, remove prefix ready for the next check
                         $uri_c = substr_replace($uri_c, '', 0, strlen($sanitized_prefix));
                     }
                 }
                 // Check suffix
                 if ($check_type && $suffix && $this->pref('show_suffix')) {
                     $sanitized_suffix = urldecode($this->encode_url($suffix));
                     if (($pos = strrpos($uri_c, $sanitized_suffix)) === false) {
                         $check_type = false;
                         $this->debug('Can\'t find suffix: ' . $suffix);
                     } else {
                         // Check passed, remove suffix ready for the next check
                         $uri_c = substr_replace($uri_c, '', $pos, strlen($sanitized_suffix));
                     }
                 }
                 // Both the prefix and suffix settings have passed
                 if ($check_type) {
                     $this->debug('Checking if "' . $uri_c . '" is of type "' . $type . '"');
                     $uri_c = doSlash($uri_c);
                     //
                     if ($prefs['permalink_title_format']) {
                         $mt_search = array('/_/', '/\\.html$/');
                         $mt_replace = array('-', '');
                     } else {
                         $mt_search = array('/(?:^|_)(.)/e', '/\\.html$/');
                         $mt_replace = array("strtoupper('\\1')", '');
                     }
                     $mt_uri_c = $this->pref('redirect_mt_style_links') ? preg_replace($mt_search, $mt_replace, $uri_c) : '';
                     // Compare based on type
                     switch ($type) {
                         case 'section':
                             if ($rs = safe_row('name', 'txp_section', "(`name` like '{$uri_c}' or `name` like '{$mt_uri_c}') limit 1")) {
                                 $this->debug('Section name: ' . $rs['name']);
                                 $pretext_replacement['s'] = $rs['name'];
                                 $context[] = "`Section` = '{$rs['name']}'";
                                 $match = true;
                             }
                             break;
                         case 'category':
                             if ($rs = safe_row('name', 'txp_category', "(`name` like '{$uri_c}' or `name` like '{$mt_uri_c}') and `type` = 'article' limit 1")) {
                                 $this->debug('Category name: ' . $rs['name']);
                                 $pretext_replacement['c'] = $rs['name'];
                                 $context[] = "(`Category1` = '{$rs['name']}' OR `Category2` = '{$uri_c}')";
                                 $match = true;
                             }
                             break;
                         case 'title':
                             if ($rs = safe_row('url_title', 'textpattern', "(`url_title` like '{$uri_c}' or `url_title` like '{$mt_uri_c}') {$context_str} and `Status` >= 4 limit 1")) {
                                 $this->debug('URL Title: ' . $rs['url_title']);
                                 $mt_redirect = $uri_c != $mt_uri_c;
                                 $pretext_replacement['url_title'] = $rs['url_title'];
                                 $match = true;
                             }
                             break;
                         case 'id':
                             if ($rs = safe_row('ID, Posted', 'textpattern', "`ID` = '{$uri_c}' {$context_str} and `Status` >= 4 limit 1")) {
                                 $pretext_replacement['id'] = $rs['ID'];
                                 $pretext_replacement['Posted'] = $rs['Posted'];
                                 $pretext['numPages'] = 1;
                                 $pretext['is_article_list'] = false;
                                 $match = true;
                             }
                             break;
                         case 'author':
                             if ($author = safe_field('name', 'txp_users', "RealName like '{$uri_c}' limit 1")) {
                                 $pretext_replacement['author'] = $author;
                                 $context[] = "`AuthorID` = '{$author}'";
                                 $match = true;
                             }
                             break;
                         case 'login':
                             if ($author = safe_field('name', 'txp_users', "name like '{$uri_c}' limit 1")) {
                                 $pretext_replacement['author'] = $author;
                                 $context[] = "`AuthorID` = '{$author}'";
                                 $match = true;
                             }
                             break;
                         case 'custom':
                             $custom_options = array_values(array_map(array($this, "encode_url"), safe_column("custom_{$custom}", 'textpattern', "custom_{$custom} != ''")));
                             if ($this->pref('force_lowercase_urls')) {
                                 $custom_options = array_map("strtolower", $custom_options);
                             }
                             if (in_array($uri_c, $custom_options)) {
                                 $match = true;
                             }
                             break;
                         case 'date':
                             if (preg_match('/^\\d{4}\\/\\d{2}\\/\\d{2}$/', $uri_c)) {
                                 $pretext_replacement['date'] = str_replace('/', '-', $uri_c);
                                 $match = true;
                             }
                             break;
                         case 'year':
                             if (preg_match('/^\\d{4}$/', $uri_c)) {
                                 $pretext_replacement['year'] = $uri_c;
                                 $match = true;
                             }
                             break;
                         case 'month':
                         case 'day':
                             if (preg_match('/^\\d{2}$/', $uri_c)) {
                                 $pretext_replacement[$type] = $uri_c;
                                 $match = true;
                             }
                             break;
                         case 'page':
                             if (is_numeric($uri_c)) {
                                 $pretext_replacement['pg'] = $uri_c;
                                 $match = true;
                             }
                             break;
                         case 'feed':
                             if (in_array($uri_c, array('rss', 'atom'))) {
                                 $pretext_replacement[$uri_c] = 1;
                                 $match = true;
                             }
                             break;
                         case 'search':
                             $pretext_replacement['q'] = $uri_c;
                             $match = true;
                             break;
                         case 'text':
                             if ($this->encode_url($text) == $uri_c) {
                                 $match = true;
                                 $pretext_replacement["permlink_text_{$name}"] = $uri_c;
                             }
                             break;
                         case 'regex':
                             // Check to see if regex is valid without outputting error messages.
                             ob_start();
                             preg_match($regex, $uri_c, $regex_matches);
                             $is_valid_regex = !ob_get_clean();
                             if ($is_valid_regex && @$regex_matches[0]) {
                                 $match = true;
                                 $pretext_replacement["permlink_regex_{$name}"] = $regex_matches[0];
                             }
                             break;
                     }
                     // switch type end
                     // Update the article context string
                     $context_str = count($context) > 0 ? 'and ' . join(' and ', $context) : '';
                     $this->debug($match == true ? 'YES' : 'NO');
                     if (!$match && !$cleaver_partial_match && $this->pref('use_cleaver_partial_matches')) {
                         // There hasn't been a match or a complete cleaver partial match. Lets try to be cleaver and
                         // check to see if this component is either a title, page or a feed. This makes it more probable
                         // a successful match for a given permlink rule occurs.
                         $this->debug('Checking if "' . $uri_c . '" is of type "title_page_feed"');
                         if ($type != 'title' && ($url_title = safe_field('url_title', 'textpattern', "`url_title` like '{$uri_c}' {$context_str} and `Status` >= 4 limit 1"))) {
                             $pretext_replacement['url_title'] = $url_title;
                             $pretext['numPages'] = 1;
                             $pretext['is_article_list'] = false;
                             $cleaver_partial_match = true;
                         } else {
                             if ($this->pref('clean_page_archive_links') && $type != 'page' && is_numeric($uri_c)) {
                                 $pretext_replacement['pg'] = $uri_c;
                                 $cleaver_partial_match = true;
                             } else {
                                 if ($type != 'feed' && in_array($uri_c, array('rss', 'atom'))) {
                                     $pretext_replacement[$uri_c] = 1;
                                     $cleaver_partial_match = true;
                                 }
                             }
                         }
                         $this->debug($cleaver_partial_match == true ? 'YES' : 'NO');
                         if ($cleaver_partial_match) {
                             $this->cleaver_partial_match = $pretext_replacement;
                             // Unset pretext_replacement as changes could of been made in a preceding component
                             unset($pretext_replacement);
                             $cleaver_partial_match = true;
                             continue 2;
                         }
                     }
                 }
                 // check type end
                 // Break early if the component doesn't match, as there is no point continuing
                 if ($match == false) {
                     // Unset pretext_replacement as changes could of been made in a preceding component
                     unset($pretext_replacement);
                     break;
                 }
             }
             // foreach permlink component end
             if (!isset($pretext_replacement['id'])) {
                 if (isset($pretext_replacement['url_title'])) {
                     if (isset($pretext_replacement['date'])) {
                         $date_val = $pretext_replacement['date'];
                     } else {
                         if (isset($pretext_replacement['year'])) {
                             $date_val = $pretext_replacement['year'];
                             if (isset($pretext_replacement['month'])) {
                                 $date_val .= '-' . $pretext_replacement['month'];
                                 if (isset($pretext_replacement['day'])) {
                                     $date_val .= '-' . $pretext_replacement['day'];
                                 }
                             }
                         }
                     }
                     if (isset($date_val)) {
                         $context_str .= " and `Posted` like '{$date_val}%'";
                     }
                     if ($rs = safe_row('ID, Posted', 'textpattern', "`url_title` like '{$pretext_replacement['url_title']}' {$context_str} and `Status` >= 4 order by `Posted` desc limit 1")) {
                         if (isset($date_val)) {
                             $this->debug('Found date and title-based match.');
                         } else {
                             $this->debug('Found title-based match.');
                         }
                         $pretext_replacement['id'] = $rs['ID'];
                         $pretext_replacement['Posted'] = $rs['Posted'];
                         $pretext['numPages'] = 1;
                         $pretext['is_article_list'] = false;
                     } else {
                         $match = false;
                         unset($pretext_replacement);
                     }
                 }
             }
             if ($match || $partial_match || $cleaver_partial_match) {
                 // Extract the settings for this permlink
                 @extract($permlinks[$pretext_replacement['permlink_id']]['settings']);
                 // Check the permlink section and category conditions
                 if (!empty($con_section) && $con_section != @$pretext_replacement['s'] || !empty($con_category) && $con_category != @$pretext_replacement['c']) {
                     $this->debug('Permlink conditions failed');
                     if (@$con_section) {
                         $this->debug('con_section = ' . $con_section);
                     }
                     if (@$con_category) {
                         $this->debug('con_category = ' . $con_category);
                     }
                     unset($pretext_replacement);
                 } else {
                     if ($match && isset($pretext_replacement)) {
                         $this->debug('We have a match!');
                     } else {
                         if ($partial_match && count($this->partial_matches)) {
                             $this->debug('We have a \'partial match\'');
                         } else {
                             if ($cleaver_partial_match && isset($cleaver_partial_match)) {
                                 $this->debug('We have a \'cleaver partial match\'');
                             } else {
                                 $this->debug('Error: Can\'t determine the correct type match');
                                 // This permlink has failed, continue execution of the foreach permlinks loop
                                 unset($pretext_replacement);
                             }
                         }
                     }
                 }
             }
             // We have a match
             if (@$pretext_replacement) {
                 break;
             }
         }
         // foreach permlinks end
         // If there is no match restore the most likely partial match. Sorted by number of components and then precedence
         if (!@$pretext_replacement && count($this->partial_matches)) {
             $pt_slice = array_slice($this->partial_matches, -1);
             $pretext_replacement = array_shift($pt_slice);
         }
         unset($this->partial_matches);
         // Restore the cleaver_partial_match if there is no other matches
         if (!@$pretext_replacement && $this->cleaver_partial_match) {
             $pretext_replacement = $this->cleaver_partial_match;
         }
         unset($this->cleaver_partial_match);
         // Extract the settings for this permlink
         @extract($permlinks[$pretext_replacement['permlink_id']]['settings']);
         // If pretext_replacement is still set here then we have a match
         if (@$pretext_replacement) {
             $this->debug('Pretext Replacement ' . print_r($pretext_replacement, 1));
             if (!empty($des_section)) {
                 $pretext_replacement['s'] = $des_section;
             }
             if (!empty($des_category)) {
                 $pretext_replacement['c'] = $des_category;
             }
             if (!empty($des_feed)) {
                 $pretext_replacement[$des_feed] = 1;
             }
             if (@$pretext_replacement['id'] && @$pretext_replacement['Posted']) {
                 if ($np = getNextPrev($pretext_replacement['id'], $pretext_replacement['Posted'], @$pretext_replacement['s'])) {
                     $pretext_replacement = array_merge($pretext_replacement, $np);
                 }
             }
             unset($pretext_replacement['Posted']);
             // If there is a match then we most set the http status correctly as txp's pretext might set it to 404
             $pretext_replacement['status'] = '200';
             // Store the orginial HTTP status code
             // We might need to log the page hit if it equals 404
             $orginial_status = $pretext['status'];
             // Txp only looks at the month, but due to how we phase the month we can manipulate the sql to our needs
             if (array_key_exists('date', $pretext_replacement)) {
                 $pretext_replacement['month'] = $pretext_replacement['date'];
                 unset($pretext_replacement['date']);
             } else {
                 if (array_key_exists('year', $pretext_replacement) || array_key_exists('month', $pretext_replacement) || array_key_exists('day', $pretext_replacement)) {
                     $month = '';
                     $month .= array_key_exists('year', $pretext_replacement) ? $pretext_replacement['year'] . '-' : '____-';
                     $month .= array_key_exists('month', $pretext_replacement) ? $pretext_replacement['month'] . '-' : '__-';
                     $month .= array_key_exists('day', $pretext_replacement) ? $pretext_replacement['day'] . ' ' : '__ ';
                     $pretext_replacement['month'] = $month;
                     unset($pretext_replacement['year']);
                     unset($pretext_replacement['day']);
                 }
             }
             // Section needs to be defined so we can always get a page template.
             if (!array_key_exists('s', $pretext_replacement)) {
                 if (!@$pretext_replacement['id']) {
                     $pretext_replacement['s'] = 'default';
                 } else {
                     $pretext_replacement['s'] = safe_field('Section', 'textpattern', 'ID = ' . $pretext_replacement['id']);
                 }
             }
             // Set the css and page template, otherwise we get an unknown section
             $section_settings = safe_row('css, page', 'txp_section', "name = '{$pretext_replacement['s']}' limit 1");
             $pretext_replacement['page'] = @$des_page ? $des_page : $section_settings['page'];
             $pretext_replacement['css'] = $section_settings['css'];
             $this->matched_permlink = $pretext_replacement;
             global $permlink_mode;
             if (in_array($prefs['permlink_mode'], array('id_title', 'section_id_title')) && @$pretext_replacement['pg'] && !@$pretext_replacement['id']) {
                 $pretext_replacement['id'] = '';
                 $pretext_replacement['is_article_list'] = true;
             }
             // Merge pretext_replacement with pretext
             $pretext = array_merge($pretext, $pretext_replacement);
             if (is_numeric(@$pretext['id'])) {
                 $a = safe_row('*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod', 'textpattern', 'ID=' . intval($pretext['id']) . ' and Status >= 4');
                 populateArticleData($a);
             }
             // Export required values to the global namespace
             foreach (array('id', 's', 'c', 'pg', 'is_article_list', 'prev_id', 'prev_title', 'next_id', 'next_title', 'css') as $key) {
                 if (array_key_exists($key, $pretext)) {
                     $GLOBALS[$key] = $pretext[$key];
                 }
             }
             if (count($this->matched_permlink) || @$mt_redirect) {
                 $pl_index = $pretext['permlink_id'];
                 if (!@$mt_redirect || !$this->pref('redirect_mt_style_links')) {
                     $pl = $this->get_permlink($pretext['permlink_id']);
                     $pl_index = @$pl['settings']['des_permlink'];
                 }
                 if (@$pretext['id'] && $pl_index) {
                     if (count($this->get_permlink($pl_index)) > 0) {
                         ob_clean();
                         global $siteurl;
                         $rs = safe_row('*, ID as thisid, unix_timestamp(Posted) as posted', 'textpattern', "ID = '{$pretext['id']}'");
                         $host = rtrim(str_replace(rtrim(doStrip($pretext['subpath']), '/'), '', hu), '/');
                         $this->redirect($host . $this->_permlinkurl($rs, PERMLINKURL, $pl_index), $this->pref('permlink_redirect_http_status'));
                     }
                 } else {
                     if ($url = @$pl['settings']['des_location']) {
                         ob_clean();
                         $this->redirect($url, $this->pref('url_redirect_http_status'));
                     }
                 }
             }
             if (@$pretext['rss']) {
                 if (@$pretext['s']) {
                     $_POST['section'] = $pretext['s'];
                 }
                 if (@$pretext['c']) {
                     $_POST['category'] = $pretext['c'];
                 }
                 ob_clean();
                 include txpath . '/publish/rss.php';
                 exit(rss());
             }
             if (@$pretext['atom']) {
                 if (@$pretext['s']) {
                     $_POST['section'] = $pretext['s'];
                 }
                 if (@$pretext['c']) {
                     $_POST['category'] = $pretext['c'];
                 }
                 ob_clean();
                 include txpath . '/publish/atom.php';
                 exit(atom());
             }
             $this->debug('Pretext ' . print_r($pretext, 1));
         } else {
             $this->debug('NO CHANGES MADE');
         }
         // Log this page hit
         if (@$orginial_status == 404) {
             log_hit($pretext['status']);
         }
         // Start output buffering and pseudo callback to textpattern_end
         ob_start(array(&$this, '_textpattern_end_callback'));
         // TxP 4.0.5 (r2436) introduced the textpattern_end callback making the following redundant
         $version = array_sum(array_map(create_function('$line', 'if (preg_match(\'/^\\$' . 'LastChangedRevision: (\\w+) \\$/\', $line, $match)) return $match[1];'), @file(txpath . '/publish.php')));
         if ($version >= '2436') {
             return;
         }
         // Remove the plugin callbacks which have already been called
         function filter_callbacks($c)
         {
             if ($c['event'] != 'textpattern') {
                 return true;
             }
             if (@$c['function'][0]->plugin_name == 'gbp_permanent_links' && @$c['function'][1] == '_textpattern') {
                 $GLOBALS['gbp_found_self'] = true;
                 return false;
             }
             return @$GLOBALS['gbp_found_self'];
         }
         $plugin_callback = array_filter($plugin_callback, 'filter_callbacks');
         unset($GLOBALS['gbp_found_self']);
         // Re-call textpattern
         textpattern();
         // Call custom textpattern_end callback
         $this->_textpattern_end();
         // textpattern() has run, kill the connection
         die;
     }
 }
Esempio n. 13
0
function render_feed($rs, $area, $type, $feedtitle, $atom_self_ref, $atom_id_ext)
{
    global $prefs, $thisarticle;
    extract($prefs);
    set_error_handler('tagErrorHandler');
    $atom = $type == 'atom';
    if ($atom) {
        define("t_texthtml", ' type="text/html"');
        define("t_text", ' type="text"');
        define("t_html", ' type="html"');
        define("t_xhtml", ' type="xhtml"');
        define('t_appxhtml', ' type="xhtml"');
        define("r_relalt", ' rel="alternate"');
        define("r_relself", ' rel="self"');
    } else {
        define("t_texthtml", '');
        define("t_text", '');
        define("t_html", '');
        define("t_xhtml", '');
        define('t_appxhtml', '');
        define("r_relalt", '');
        define("r_relself", '');
    }
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    if ($atom) {
        $out[] = tag('Textpattern', 'generator', ' uri="http://textpattern.com/" version="' . $version . '"');
        $out[] = tag(htmlspecialchars($feedtitle), 'title', t_text);
        $out[] = tag(htmlspecialchars($site_slogan), 'subtitle', t_text);
        $out[] = tag(safe_strftime("w3cdtf", $last), 'updated');
        $out[] = '<link' . r_relself . ' href="' . $atom_self_ref . '" />';
        $out[] = '<link' . r_relalt . t_texthtml . ' href="' . hu . '" />';
        //Atom feeds with mail or domain name
        $out[] = tag('tag:' . $mail_or_domain . ',' . $blog_time_uid . ':' . $blog_uid . $atom_id_ext, 'id');
        $pub = safe_row("RealName, email", "txp_users", "privs=1");
        $auth[] = tag($pub['RealName'], 'name');
        $auth[] = $include_email_atom ? tag(eE($pub['email']), 'email') : '';
        $auth[] = tag(hu, 'uri');
        $out[] = tag(n . t . t . join(n . t . t, $auth) . n, 'author');
    } else {
        $out[] = tag('http://textpattern.com/?v=' . $version, 'generator');
        $out[] = tag(doSpecial($feedtitle), 'title');
        $out[] = tag(doSpecial($site_slogan), 'description');
        $out[] = tag(safe_strftime('rfc822', $last), 'pubDate');
        $out[] = tag(hu, 'link');
        $out[] = '<atom:link href="' . $atom_self_ref . '" rel="self" type="application/rss+xml" />';
    }
    $out[] = callback_event($atom ? 'atom_head' : 'rss_head');
    $articles = array();
    if (!$area or $area == 'article') {
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event($atom ? 'atom_entry' : 'rss_entry');
                $e = array();
                $thisauthor = doSpecial(get_author_name($AuthorID));
                $thisauthor = tag($thisauthor, $atom ? 'name' : 'dc:creator');
                if ($atom) {
                    $thisauthor = tag(n . t . t . t . $thisauthor . n . t . t, 'author');
                }
                $e['thisauthor'] = $thisauthor;
                if ($atom) {
                    $e['issued'] = tag(safe_strftime('w3cdtf', $uPosted), 'published');
                } else {
                    $e['issued'] = tag(safe_strftime('rfc822', $uPosted), 'pubDate');
                }
                if ($atom) {
                    $e['modified'] = tag(safe_strftime('w3cdtf', $uLastMod), 'updated');
                    $e['category1'] = trim($Category1) ? '<category term="' . doSpecial($Category1) . '" />' : '';
                    $e['category2'] = trim($Category2) ? '<category term="' . doSpecial($Category2) . '" />' : '';
                }
                $count = '';
                if ($show_comment_count_in_feed && $comments_count > 0) {
                    $count = ' [' . $comments_count . ']';
                }
                $escaped_title = $atom ? htmlspecialchars($Title) : htmlspecialchars(strip_tags($Title));
                $e['title'] = tag($escaped_title . $count, 'title', t_html);
                $a['posted'] = $uPosted;
                $permlink = permlinkurl($a);
                if ($atom) {
                    $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $permlink . '" />';
                } else {
                    $e['link'] = tag($permlink, 'link');
                }
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, $atom ? 'id' : 'guid', $atom ? '' : ' isPermaLink="false"');
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    # short feed: use body as summary if there's no excerpt
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if (trim($summary)) {
                    $e['summary'] = tag(n . escape_cdata($summary) . n, $atom ? 'summary' : 'description', t_html);
                }
                if (trim($content)) {
                    $e['content'] = tag(n . escape_cdata($content) . n, $atom ? 'content' : 'content:encoded', t_html);
                }
                $articles[$ID] = tag(n . t . t . join(n . t . t, $e) . n . $cb, $atom ? 'entry' : 'item');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $atom ? $uLastMod : $uPosted;
            }
        }
    } elseif ($area == 'link') {
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $e['title'] = tag(doSpecial($linkname), 'title', t_html);
                if ($atom) {
                    $e['content'] = tag(n . doSpecial($description) . n, 'content', t_html);
                    $url = preg_replace("/^\\/(.*)/", "https?://{$siteurl}/\$1", $url);
                    $url = preg_replace("/&((?U).*)=/", "&amp;\\1=", $url);
                    $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $url . '" />';
                    $e['issued'] = tag(safe_strftime('w3cdtf', strtotime($date)), 'published');
                    $e['modified'] = tag(gmdate('Y-m-d\\TH:i:s\\Z', strtotime($date)), 'updated');
                    $e['id'] = tag('tag:' . $mail_or_domain . ',' . safe_strftime('%Y-%m-%d', strtotime($date)) . ':' . $blog_uid . '/' . $id, 'id');
                } else {
                    $e['content'] = tag(doSpecial($description), 'description');
                    $e['link'] = tag(doSpecial($url), 'link');
                    $e['issued'] = tag(safe_strftime('rfc822', $uDate), 'pubDate');
                }
                $articles[$id] = tag(n . t . t . join(n . t . t, $e) . n, $atom ? 'entry' : 'item');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!$articles) {
        if ($section) {
            if (safe_field('name', 'txp_section', "name = '{$section}'") == false) {
                txp_die(gTxt('404_not_found'), '404');
            }
        } elseif ($category) {
            switch ($area) {
                case 'link':
                    if (safe_field('id', 'txp_category', "name = '{$category}' and type = 'link'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
                case 'article':
                default:
                    if (safe_field('id', 'txp_category', "name = '{$category}' and type = 'article'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
            }
        }
    } else {
        //turn on compression if we aren't using it already
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            // make sure notices/warnings/errors don't
            // fudge up the feed when compression is used
            $buf = '';
            while ($b = @ob_get_clean()) {
                $buf .= $b;
            }
            @ob_start('ob_gzhandler');
            echo $buf;
        }
        handle_lastmod();
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        $imsd = $hims ? strtotime($hims) : 0;
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id]) !== false) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } else {
            if (isset($cut_etag)) {
                header("Vary: If-None-Match");
            } else {
                if (isset($cut_time)) {
                    header("Vary: If-Modified-Since");
                }
            }
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            txp_status_header('304 Not Modified');
            exit(0);
        }
        if ($etag) {
            header('ETag: "' . $etag . '"');
        }
        if ($cutarticles) {
            //header("HTTP/1.1 226 IM Used");
            //This should be used as opposed to 200, but Apache doesn't like it.
            //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
    }
    $out = array_merge($out, $articles);
    header('Content-type: application/' . ($atom ? 'atom' : 'rss') . '+xml; charset=utf-8');
    if ($atom) {
        return chr(60) . '?xml version="1.0" encoding="UTF-8"?' . chr(62) . n . '<feed xml:lang="' . $language . '" xmlns="http://www.w3.org/2005/Atom">' . n . join(n, $out) . '</feed>';
    } else {
        return '<?xml version="1.0" encoding="utf-8"?>' . n . '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">' . n . tag(join(n, $out), 'channel') . n . '</rss>';
    }
}
Esempio n. 14
0
function rss()
{
    global $prefs, $thisarticle;
    extract($prefs);
    extract(doSlash(gpsa(array('category', 'section', 'limit', 'area'))));
    $area = gps('area');
    $sitename .= $section ? ' - ' . $section : '';
    $sitename .= $category ? ' - ' . $category : '';
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    $out[] = tag('http://textpattern.com/?v=' . $version, 'generator');
    $out[] = tag(doSpecial($sitename), 'title');
    $out[] = tag(hu, 'link');
    $out[] = tag(doSpecial($site_slogan), 'description');
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    $out[] = tag(safe_strftime('rfc822', $last), 'pubDate');
    $articles = array();
    if (!$area or $area == 'article') {
        $sfilter = $section ? "and Section = '" . $section . "'" : '';
        $cfilter = $category ? "and (Category1='" . $category . "' or Category2='" . $category . "')" : '';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $frs = safe_column("name", "txp_section", "in_rss != '1'");
        if ($frs) {
            foreach ($frs as $f) {
                $query[] = "and Section != '" . doSlash($f) . "'";
            }
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, ID as thisid", "textpattern", "Status = 4 " . join(' ', $query) . "and Posted < now() order by Posted desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event('rss_entry');
                $a['posted'] = $uPosted;
                $permlink = permlinkurl($a);
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    # short feed: use body as summary if there's no excerpt
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if ($show_comment_count_in_feed) {
                    $count = $comments_count > 0 ? ' [' . $comments_count . ']' : '';
                } else {
                    $count = '';
                }
                $Title = escape_output(strip_tags($Title)) . $count;
                $thisauthor = get_author_name($AuthorID);
                $item = tag($Title, 'title') . n . (trim($summary) ? tag(n . escape_cdata($summary) . n, 'description') . n : '') . (trim($content) ? tag(n . escape_cdata($content) . n, 'content:encoded') . n : '') . tag($permlink, 'link') . n . tag(safe_strftime('rfc822', $a['posted']), 'pubDate') . n . tag(htmlspecialchars($thisauthor), 'dc:creator') . n . tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'guid', ' isPermaLink="false"') . n . $cb;
                $articles[$ID] = tag($item, 'item');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uPosted;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category='{$category}'" : '1';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $rs = safe_rows_start("*, unix_timestamp(date) as uDate", "txp_link", "{$cfilter} order by date desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $item = tag(doSpecial($linkname), 'title') . n . tag(doSpecial($description), 'description') . n . tag(doSpecial($url), 'link') . n . tag(safe_strftime('rfc822', $uDate), 'pubDate');
                $articles[$id] = tag($item, 'item');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    //turn on compression if we aren't using it already
    if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
        @ob_start("ob_gzhandler");
    }
    handle_lastmod();
    $hims = serverset('HTTP_IF_MODIFIED_SINCE');
    $imsd = $hims ? strtotime($hims) : 0;
    if (is_callable('apache_request_headers')) {
        $headers = apache_request_headers();
        if (isset($headers["A-IM"])) {
            $canaim = strpos($headers["A-IM"], "feed");
        } else {
            $canaim = false;
        }
    } else {
        $canaim = false;
    }
    $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
    $cutarticles = false;
    if ($canaim !== false) {
        foreach ($articles as $id => $thing) {
            if (strpos($hinm, $etags[$id]) !== false) {
                unset($articles[$id]);
                $cutarticles = true;
                $cut_etag = true;
            }
            if ($dates[$id] < $imsd) {
                unset($articles[$id]);
                $cutarticles = true;
                $cut_time = true;
            }
        }
    }
    if (isset($cut_etag) && isset($cut_time)) {
        header("Vary: If-None-Match, If-Modified-Since");
    } else {
        if (isset($cut_etag)) {
            header("Vary: If-None-Match");
        } else {
            if (isset($cut_time)) {
                header("Vary: If-Modified-Since");
            }
        }
    }
    $etag = @join("-", $etags);
    if (strstr($hinm, $etag)) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }
    if ($cutarticles) {
        //header("HTTP/1.1 226 IM Used");
        //This should be used as opposed to 200, but Apache doesn't like it.
        //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
        header("Cache-Control: no-store, im");
        header("IM: feed");
    }
    $out = array_merge($out, $articles);
    header("Content-Type: application/rss+xml; charset=utf-8");
    if ($etag) {
        header('ETag: "' . $etag . '"');
    }
    return '<?xml version="1.0" encoding="utf-8"?>' . n . '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">' . n . tag(join(n, $out), 'channel') . n . '</rss>';
}
Esempio n. 15
0
function rss()
{
    global $prefs, $thisarticle;
    extract($prefs);
    ob_start();
    extract(doSlash(gpsa(array('category', 'section', 'limit', 'area'))));
    $area = gps('area');
    $sitename .= $section ? ' - ' . $section : '';
    $sitename .= $category ? ' - ' . $category : '';
    $out[] = tag(doSpecial($sitename), 'title');
    $out[] = tag(hu, 'link');
    $out[] = tag(doSpecial($site_slogan), 'description');
    $articles = array();
    if (!$area or $area == 'article') {
        $sfilter = $section ? "and Section = '" . $section . "'" : '';
        $cfilter = $category ? "and (Category1='" . $category . "' or Category2='" . $category . "')" : '';
        $limit = $limit ? $limit : '5';
        $frs = safe_column("name", "txp_section", "in_rss != '1'");
        if ($frs) {
            foreach ($frs as $f) {
                $query[] = "and Section != '" . $f . "'";
            }
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, ID as thisid", "textpattern", "Status = 4 " . join(' ', $query) . "and Posted < now() order by Posted desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $a['posted'] = $uPosted;
                $Body = !$syndicate_body_or_excerpt ? $thisarticle['body'] : $thisarticle['excerpt'];
                $Body = !trim($Body) ? $thisarticle['body'] : $Body;
                $Body = str_replace('href="/', 'href="' . hu, $Body);
                $Body = preg_replace("/href=\\\"#(.*)\"/", "href=\"" . permlinkurl($a) . "#\\1\"", $Body);
                $Body = safe_hed($Body);
                $Body = preg_replace(array('/</', '/>/', "/'/", '/"/'), array('&lt;', '&gt;', '&#039;', '&quot;'), $Body);
                // encode bare ampersands
                $Body = preg_replace("/&(?![#0-9]+;|\\w+;)/i", '&amp;', $Body);
                $uTitle = $url_title ? $url_title : stripSpace($Title);
                $uTitle = htmlspecialchars($uTitle, ENT_NOQUOTES);
                if ($show_comment_count_in_feed) {
                    $dc = getCount('txp_discuss', "parentid={$ID} and visible=1");
                    $count = $dc > 0 ? ' [' . $dc . ']' : '';
                } else {
                    $count = '';
                }
                $Title = doSpecial($Title) . $count;
                $permlink = permlinkurl($a);
                $item = tag(strip_tags($Title), 'title') . n . tag($Body, 'description') . n . tag($permlink, 'link');
                $articles[$ID] = tag($item, 'item');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uPosted;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category='{$category}'" : '1';
        $limit = $limit ? $limit : 15;
        $rs = safe_rows_start("*", "txp_link", "{$cfilter} order by date desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $item = tag(doSpecial($linkname), 'title') . n . tag(doSpecial($description), 'description') . n . tag(doSpecial($url), 'link');
                $articles[$id] = tag($item, 'item');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    //turn on compression if we aren't using it already
    if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
        ob_start("ob_gzhandler");
    }
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    $last = gmdate("D, d M Y H:i:s \\G\\M\\T", $last);
    header("Last-Modified: {$last}");
    $expires = gmdate('D, d M Y H:i:s \\G\\M\\T', time() + 3600 * 1);
    header("Expires: {$expires}");
    $hims = serverset('HTTP_IF_MODIFIED_SINCE');
    if ($hims == $last) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }
    $imsd = @strtotime($hims);
    if (is_callable('apache_request_headers')) {
        $headers = apache_request_headers();
        if (isset($headers["A-IM"])) {
            $canaim = strpos($headers["A-IM"], "feed");
        } else {
            $canaim = false;
        }
    } else {
        $canaim = false;
    }
    $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
    $cutarticles = false;
    if ($canaim !== false) {
        foreach ($articles as $id => $thing) {
            if (strpos($hinm, $etags[$id]) !== false) {
                unset($articles[$id]);
                $cutarticles = true;
                $cut_etag = true;
            }
            if ($dates[$id] < $imsd) {
                unset($articles[$id]);
                $cutarticles = true;
                $cut_time = true;
            }
        }
    }
    if (isset($cut_etag) && isset($cut_time)) {
        header("Vary: If-None-Match, If-Modified-Since");
    } else {
        if (isset($cut_etag)) {
            header("Vary: If-None-Match");
        } else {
            if (isset($cut_time)) {
                header("Vary: If-Modified-Since");
            }
        }
    }
    $etag = @join("-", $etags);
    if (strstr($hinm, $etag)) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }
    if ($cutarticles) {
        //header("HTTP/1.1 226 IM Used");
        //This should be used as opposed to 200, but Apache doesn't like it.
        //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
        header("Cache-Control: no-store, im");
        header("IM: feed");
    }
    $out = array_merge($out, $articles);
    header("Content-Type: application/rss+xml; charset=utf-8");
    if ($etag) {
        header('ETag: "' . $etag . '"');
    }
    return '<rss version="0.92">' . tag(join(n, $out), 'channel') . '</rss>';
}
Esempio n. 16
0
function doArticle($atts)
{
    global $pretext, $prefs, $thisarticle;
    extract($prefs);
    extract($pretext);
    extract(gpsa(array('parentid', 'preview')));
    extract(lAtts(array('allowoverride' => '1', 'form' => 'default', 'status' => '4'), $atts, 0));
    if ($status and !is_numeric($status)) {
        $status = getStatusNum($status);
    }
    if (empty($thisarticle) or $thisarticle['thisid'] != $id) {
        $thisarticle = NULL;
        $q_status = $status ? 'and Status = ' . intval($status) : 'and Status in (4,5)';
        $rs = safe_row("*, unix_timestamp(Posted) as uPosted", "textpattern", 'ID = ' . intval($id) . " {$q_status} limit 1");
        if ($rs) {
            extract($rs);
            populateArticleData($rs);
        }
    }
    if (!empty($thisarticle) and $thisarticle['status'] == $status) {
        extract($thisarticle);
        $thisarticle['is_first'] = 1;
        $thisarticle['is_last'] = 1;
        $form = ($allowoverride and $override_form) ? $override_form : $form;
        $article = parse_form($form);
        if ($use_comments and $comments_auto_append) {
            $article .= parse_form('comments_display');
        }
        unset($GLOBALS['thisarticle']);
        return $article;
    }
}
Esempio n. 17
0
function rss()
{
    global $prefs, $thisarticle;
    set_error_handler('feedErrorHandler');
    ob_clean();
    extract($prefs);
    extract(doSlash(gpsa(array('limit', 'area'))));
    // build filter criteria from a comma-separated list of sections and categories
    $feed_filter_limit = get_pref('feed_filter_limit', 10);
    $section = gps('section');
    $category = gps('category');
    if (!is_scalar($section) || !is_scalar($category)) {
        txp_die('Not Found', 404);
    }
    $section = $section ? array_slice(array_unique(do_list($section)), 0, $feed_filter_limit) : array();
    $category = $category ? array_slice(array_unique(do_list($category)), 0, $feed_filter_limit) : array();
    $st = array();
    foreach ($section as $s) {
        $st[] = fetch_section_title($s);
    }
    $ct = array();
    foreach ($category as $c) {
        $ct[] = fetch_category_title($c);
    }
    $sitename .= $section ? ' - ' . join(' - ', $st) : '';
    $sitename .= $category ? ' - ' . join(' - ', $ct) : '';
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    // feed header
    $out[] = tag('http://textpattern.com/?v=' . $version, 'generator');
    $out[] = tag(doSpecial($sitename), 'title');
    $out[] = tag(hu, 'link');
    $out[] = '<atom:link href="' . pagelinkurl(array('rss' => 1, 'area' => $area, 'section' => $section, 'category' => $category, 'limit' => $limit)) . '" rel="self" type="application/rss+xml" />';
    $out[] = tag(doSpecial($site_slogan), 'description');
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    $out[] = tag(safe_strftime('rfc822', $last), 'pubDate');
    $out[] = callback_event('rss_head');
    // feed items
    $articles = array();
    $section = doSlash($section);
    $category = doSlash($category);
    if (!$area or $area == 'article') {
        $sfilter = !empty($section) ? "and Section in ('" . join("','", $section) . "')" : '';
        $cfilter = !empty($category) ? "and (Category1 in ('" . join("','", $category) . "') or Category2 in ('" . join("','", $category) . "'))" : '';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $frs = safe_column("name", "txp_section", "in_rss != '1'");
        if ($frs) {
            foreach ($frs as $f) {
                $query[] = "and Section != '" . doSlash($f) . "'";
            }
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $expired = $publish_expired_articles ? '' : ' and (now() <= Expires or Expires = ' . NULLDATETIME . ') ';
        $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, unix_timestamp(LastMod) as uLastMod, unix_timestamp(Expires) as uExpires, ID as thisid", "textpattern", "Status = 4 " . join(' ', $query) . "and Posted < now()" . $expired . "order by Posted desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event('rss_entry');
                $a['posted'] = $uPosted;
                $permlink = permlinkurl($a);
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    # short feed: use body as summary if there's no excerpt
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if ($show_comment_count_in_feed) {
                    $count = $comments_count > 0 ? ' [' . $comments_count . ']' : '';
                } else {
                    $count = '';
                }
                $Title = escape_title(strip_tags($Title)) . $count;
                $thisauthor = get_author_name($AuthorID);
                $item = tag($Title, 'title') . n . (trim($summary) ? tag(n . escape_cdata($summary) . n, 'description') . n : '') . (trim($content) ? tag(n . escape_cdata($content) . n, 'content:encoded') . n : '') . tag($permlink, 'link') . n . tag(safe_strftime('rfc822', $a['posted']), 'pubDate') . n . tag(htmlspecialchars($thisauthor), 'dc:creator') . n . tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'guid', ' isPermaLink="false"') . n . $cb;
                $articles[$ID] = tag($item, 'item');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uPosted;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category in ('" . join("','", $category) . "')" : '1';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $rs = safe_rows_start("*, unix_timestamp(date) as uDate", "txp_link", "{$cfilter} order by date desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $item = tag(doSpecial($linkname), 'title') . n . tag(doSpecial($description), 'description') . n . tag(doSpecial($url), 'link') . n . tag(safe_strftime('rfc822', $uDate), 'pubDate');
                $articles[$id] = tag($item, 'item');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!$articles) {
        if ($section) {
            if (safe_field('name', 'txp_section', "name in ('" . join("','", $section) . "')") == false) {
                txp_die(gTxt('404_not_found'), '404');
            }
        } elseif ($category) {
            switch ($area) {
                case 'link':
                    if (safe_field('id', 'txp_category', "name = '{$category}' and type = 'link'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
                case 'article':
                default:
                    if (safe_field('id', 'txp_category', "name in ('" . join("','", $category) . "') and type = 'article'") == false) {
                        txp_die(gTxt('404_not_found'), '404');
                    }
                    break;
            }
        }
    } else {
        //turn on compression if we aren't using it already
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            // make sure notices/warnings/errors don't fudge up the feed
            // when compression is used
            $buf = '';
            while ($b = @ob_get_clean()) {
                $buf .= $b;
            }
            @ob_start('ob_gzhandler');
            echo $buf;
        }
        handle_lastmod();
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        $imsd = $hims ? strtotime($hims) : 0;
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id]) !== false) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } else {
            if (isset($cut_etag)) {
                header("Vary: If-None-Match");
            } else {
                if (isset($cut_time)) {
                    header("Vary: If-Modified-Since");
                }
            }
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            txp_status_header('304 Not Modified');
            exit(0);
        }
        if ($cutarticles) {
            //header("HTTP/1.1 226 IM Used");
            //This should be used as opposed to 200, but Apache doesn't like it.
            //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
    }
    $out = array_merge($out, $articles);
    header("Content-Type: application/rss+xml; charset=utf-8");
    if (isset($etag)) {
        header('ETag: "' . $etag . '"');
    }
    return '<?xml version="1.0" encoding="utf-8"?>' . n . '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">' . n . tag(join(n, $out), 'channel') . n . '</rss>';
}
Esempio n. 18
0
/**
 * Formats article info and populates the current article data.
 *
 * Fills members of $thisarticle global from a database row.
 *
 * Basically just converts an article's date values to UNIX timestamps.
 * Convenience for those who prefer doing conversion in application end instead
 * of in the SQL statement.
 *
 * @param array $rs An article as an assocative array
 * @example
 * article_format_info(
 *     safe_row('*', 'textpattern', 'Status = 4 LIMIT 1')
 * )
 */
function article_format_info($rs)
{
    $rs['uPosted'] = ($unix_ts = @strtotime($rs['Posted'])) !== false ? $unix_ts : null;
    $rs['uLastMod'] = ($unix_ts = @strtotime($rs['LastMod'])) !== false ? $unix_ts : null;
    $rs['uExpires'] = ($unix_ts = @strtotime($rs['Expires'])) !== false ? $unix_ts : null;
    populateArticleData($rs);
}
Esempio n. 19
0
function atom()
{
    global $thisarticle;
    extract($GLOBALS['prefs']);
    define("t_texthtml", ' type="text/html"');
    define("t_text", ' type="text"');
    define("t_html", ' type="html"');
    define("t_xhtml", ' type="xhtml"');
    define('t_appxhtml', ' type="xhtml"');
    define("r_relalt", ' rel="alternate"');
    define("r_relself", ' rel="self"');
    $area = doSlash(gps('area'));
    extract(doSlash(gpsa(array('category', 'section', 'limit'))));
    $last = fetch('unix_timestamp(val)', 'txp_prefs', 'name', 'lastmod');
    $sitename .= $section ? ' - ' . $section : '';
    $sitename .= $category ? ' - ' . $category : '';
    $pub = safe_row("RealName, email", "txp_users", "privs=1");
    $out[] = tag(escape_output($sitename), 'title', t_text);
    $out[] = tag(escape_output($site_slogan), 'subtitle', t_text);
    $out[] = '<link' . r_relself . ' href="' . pagelinkurl(array('atom' => 1, 'area' => $area, 'section' => $section, 'category' => $category, 'limit' => $limit)) . '" />';
    $out[] = '<link' . r_relalt . t_texthtml . ' href="' . hu . '" />';
    $articles = array();
    //Atom feeds with mail or domain name
    $dn = explode('/', $siteurl);
    $mail_or_domain = $use_mail_on_feeds_id ? eE($blog_mail_uid) : $dn[0];
    $out[] = tag('tag:' . $mail_or_domain . ',' . $blog_time_uid . ':' . $blog_uid . ($section ? '/' . $section : '') . ($category ? '/' . $category : ''), 'id');
    $out[] = tag('Textpattern', 'generator', ' uri="http://textpattern.com/" version="' . $version . '"');
    $out[] = tag(safe_strftime("w3cdtf", $last), 'updated');
    $auth[] = tag($pub['RealName'], 'name');
    $auth[] = $include_email_atom ? tag(eE($pub['email']), 'email') : '';
    $auth[] = tag(hu, 'uri');
    $out[] = tag(n . t . t . join(n . t . t, $auth) . n, 'author');
    if (!$area or $area == 'article') {
        $sfilter = $section ? "and Section = '" . $section . "'" : '';
        $cfilter = $category ? "and (Category1='" . $category . "' or Category2='" . $category . "')" : '';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $frs = safe_column("name", "txp_section", "in_rss != '1'");
        $query = array();
        foreach ($frs as $f) {
            $query[] = "and Section != '" . doSlash($f) . "'";
        }
        $query[] = $sfilter;
        $query[] = $cfilter;
        $rs = safe_rows_start("*, \n\t\t\t\tID as thisid, \n\t\t\t\tunix_timestamp(Posted) as uPosted,\n\t\t\t\tunix_timestamp(LastMod) as uLastMod", "textpattern", "Status=4 and Posted <= now() " . join(' ', $query) . "order by Posted desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                populateArticleData($a);
                $cb = callback_event('atom_entry');
                $e = array();
                $a['posted'] = $uPosted;
                if ($show_comment_count_in_feed) {
                    $count = $comments_count > 0 ? ' [' . $comments_count . ']' : '';
                } else {
                    $count = '';
                }
                $thisauthor = get_author_name($AuthorID);
                $e['thisauthor'] = tag(n . t . t . t . tag(htmlspecialchars($thisauthor), 'name') . n . t . t, 'author');
                $e['issued'] = tag(safe_strftime('w3cdtf', $uPosted), 'published');
                $e['modified'] = tag(safe_strftime('w3cdtf', $uLastMod), 'updated');
                $escaped_title = escape_output($Title);
                $e['title'] = tag($escaped_title . $count, 'title', t_html);
                $permlink = permlinkurl($a);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $permlink . '" />';
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $blog_uid . '/' . $uid, 'id');
                $e['category1'] = trim($Category1) ? '<category term="' . htmlspecialchars($Category1) . '" />' : '';
                $e['category2'] = trim($Category2) ? '<category term="' . htmlspecialchars($Category2) . '" />' : '';
                $summary = trim(replace_relative_urls(parse($thisarticle['excerpt']), $permlink));
                $content = trim(replace_relative_urls(parse($thisarticle['body']), $permlink));
                if ($syndicate_body_or_excerpt) {
                    # short feed: use body as summary if there's no excerpt
                    if (!trim($summary)) {
                        $summary = $content;
                    }
                    $content = '';
                }
                if (trim($content)) {
                    $e['content'] = tag(n . escape_cdata($content) . n, 'content', t_html);
                }
                if (trim($summary)) {
                    $e['summary'] = tag(n . escape_cdata($summary) . n, 'summary', t_html);
                }
                $articles[$ID] = tag(n . t . t . join(n . t . t, $e) . n . $cb, 'entry');
                $etags[$ID] = strtoupper(dechex(crc32($articles[$ID])));
                $dates[$ID] = $uLastMod;
            }
        }
    } elseif ($area == 'link') {
        $cfilter = $category ? "category='" . $category . "'" : '1';
        $limit = $limit ? $limit : $rss_how_many;
        $limit = intval(min($limit, max(100, $rss_how_many)));
        $rs = safe_rows_start("*", "txp_link", "{$cfilter} order by date desc, id desc limit {$limit}");
        if ($rs) {
            while ($a = nextRow($rs)) {
                extract($a);
                $e['title'] = tag(htmlspecialchars($linkname), 'title', t_html);
                $e['content'] = tag(n . htmlspecialchars($description) . n, 'content', t_html);
                $url = preg_replace("/^\\/(.*)/", "https?://{$siteurl}/\$1", $url);
                $url = preg_replace("/&((?U).*)=/", "&amp;\\1=", $url);
                $e['link'] = '<link' . r_relalt . t_texthtml . ' href="' . $url . '" />';
                $e['issued'] = tag(safe_strftime('w3cdtf', strtotime($date)), 'published');
                $e['modified'] = tag(gmdate('Y-m-d\\TH:i:s\\Z', strtotime($date)), 'updated');
                $e['id'] = tag('tag:' . $mail_or_domain . ',' . $feed_time . ':' . $id, 'id');
                $articles[$id] = tag(n . t . t . join(n . t . t, $e) . n, 'entry');
                $etags[$id] = strtoupper(dechex(crc32($articles[$id])));
                $dates[$id] = $date;
            }
        }
    }
    if (!empty($articles)) {
        //turn on compression if we aren't using it already
        if (extension_loaded('zlib') && ini_get("zlib.output_compression") == 0 && ini_get('output_handler') != 'ob_gzhandler' && !headers_sent()) {
            @ob_start("ob_gzhandler");
        }
        handle_lastmod();
        $hims = serverset('HTTP_IF_MODIFIED_SINCE');
        $imsd = $hims ? strtotime($hims) : 0;
        if ($imsd >= $last) {
            txp_status_header("304 Not Modified");
            exit;
        }
        header("Last-Modified: " . gmdate('D, d M Y H:i:s \\G\\M\\T', $last));
        if (is_callable('apache_request_headers')) {
            $headers = apache_request_headers();
            if (isset($headers["A-IM"])) {
                $canaim = strpos($headers["A-IM"], "feed");
            } else {
                $canaim = false;
            }
        } else {
            $canaim = false;
        }
        $hinm = stripslashes(serverset('HTTP_IF_NONE_MATCH'));
        $cutarticles = false;
        if ($canaim !== false) {
            foreach ($articles as $id => $thing) {
                if (strpos($hinm, $etags[$id])) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_etag = true;
                }
                if ($dates[$id] < $imsd) {
                    unset($articles[$id]);
                    $cutarticles = true;
                    $cut_time = true;
                }
            }
        }
        if (isset($cut_etag) && isset($cut_time)) {
            header("Vary: If-None-Match, If-Modified-Since");
        } else {
            if (isset($cut_etag)) {
                header("Vary: If-None-Match");
            } else {
                if (isset($cut_time)) {
                    header("Vary: If-Modified-Since");
                }
            }
        }
        $etag = @join("-", $etags);
        if (strstr($hinm, $etag)) {
            header("HTTP/1.1 304 Not Modified");
            exit;
        }
        if ($etag) {
            header('ETag: "' . $etag . '"');
        }
        if ($cutarticles) {
            //header("HTTP/1.1 226 IM Used");
            //This should be used as opposed to 200, but Apache doesn't like it.
            //http://intertwingly.net/blog/2004/09/11/Vary-ETag/ says that the status code should be 200.
            header("Cache-Control: no-store, im");
            header("IM: feed");
        }
        $out = array_merge($out, $articles);
        header('Content-type: application/atom+xml; charset=utf-8');
        return chr(60) . '?xml version="1.0" encoding="UTF-8"?' . chr(62) . n . '<feed xml:lang="' . $language . '" xmlns="http://www.w3.org/2005/Atom">' . join(n, $out) . '</feed>';
    }
}
Esempio n. 20
0
function zem_event_list($atts, $thing = NULL)
{
    global $zem_thiseventcal, $pretext;
    extract(lAtts(array('wraptag' => '', 'class' => __FUNCTION__, 'break' => '', 'breakclass' => '', 'form' => 'zem_event_display', 'sort' => safe_pfx('zem_event_date') . '.event_date asc, ' . safe_pfx('zem_event_date') . '.event_time asc', 'date_from' => gps('date_from') ? gps('date_from') : 'today', 'date_to' => gps('date_to') ? gps('date_to') : '', 'date' => gps('date'), 'label' => '', 'labeltag' => '', 'limit' => '', 'category' => gps('c') ? gps('c') : @$pretext['c'], 'section' => '', 'all_categories' => gps('all_categories'), 'location' => gps('location'), 'all_locations' => gps('all_locations'), 'debug' => 0), $atts));
    if ($thing === NULL) {
        $thing = fetch_form($form);
    }
    $where = safe_pfx('zem_event_calendar') . '.id=' . safe_pfx('zem_event_date') . '.event_id and ' . safe_pfx('zem_event_calendar') . '.article_id = ' . safe_pfx('textpattern') . '.ID and ' . safe_pfx('textpattern') . '.Status >= 4 and ' . safe_pfx('textpattern') . '.Posted <= now()';
    if ($date) {
        @(list($y, $m, $d) = explode('-', $date));
        if ($y and $m and $d) {
            $date_from = $date_to = "{$y}-{$m}-{$d}";
        } elseif ($y and $m) {
            $date_from = "{$y}-{$m}-01";
            $date_to = strftime('%Y-%m-%d', strtotime('-1 day', strtotime('+1 month', strtotime($date_from))));
        } elseif ($y) {
            $date_from = "{$y}-01-01";
            $date_to = "{$y}-12-31";
        } elseif ($t = zem_strtotime($date)) {
            $date_from = strftime('%Y-%m-%d', $t);
            $date_to = strftime('%Y-%m-%d', $t);
        }
    }
    $w = zem_event_timeq($date_from, $date_to);
    if ($w) {
        $where .= ' and ' . join(' and ', $w);
    }
    if ($section) {
        $sections = do_list($section);
        $where .= " and textpattern.Section IN (" . join(',', quote_list($sections)) . ")";
    }
    if ($location and !$all_locations) {
        // location could be an array if it came from gps()
        if (is_array($location)) {
            $locs = $location;
        } else {
            $locs = do_list($location);
        }
        $where .= " and location IN (" . join(',', quote_list($locs)) . ")";
    }
    if ($q = gps('q')) {
        $where .= " and (name rlike '" . doSlash($q) . "' or description rlike '" . doSlash($q) . "')";
    }
    if ($category and !$all_categories) {
        // category could be an array if it came from gps()
        if (is_array($category)) {
            $cats = $category;
        } else {
            $cats = do_list($category);
        }
        $cats_id = safe_column('id', 'txp_category', "type='event' and name IN (" . join(',', quote_list($cats)) . ")");
        if (!$cats_id) {
            $cats_id = array(0);
        }
        $where = safe_pfx('zem_event_calendar') . ".id=" . safe_pfx('zem_event_category') . ".k1 and " . safe_pfx('zem_event_category') . ".k2 IN (" . join(',', quote_list($cats_id)) . ") and " . $where;
        $grand_total = safe_count('zem_event_calendar,zem_event_date,textpattern,zem_event_category', $where . ' group by ' . safe_pfx('zem_event_calendar') . '.id order by ' . $sort, $debug);
        $lim = zem_event_paginate($limit, $grand_total);
        $rs = safe_rows_start(safe_pfx('zem_event_calendar') . '.*, ' . safe_pfx('zem_event_date') . '.*, ' . safe_pfx('textpattern') . '.*, unix_timestamp(Posted) as uPosted', 'zem_event_calendar,zem_event_date,textpattern,zem_event_category', $where . ' group by ' . safe_pfx('zem_event_calendar') . '.id order by ' . $sort . $lim, $debug);
    } else {
        $grand_total = safe_count('zem_event_calendar,zem_event_date,textpattern', $where . ' order by ' . $sort, $debug);
        $lim = zem_event_paginate($limit, $grand_total);
        $rs = safe_rows_start('*, unix_timestamp(Posted) as uPosted', 'zem_event_calendar,zem_event_date,textpattern', $where . ' order by ' . $sort . $lim, $debug);
    }
    $out = array();
    while ($row = nextRow($rs)) {
        article_push();
        $zem_thiseventcal = $row;
        populateArticleData($row);
        $out[] = parse($thing);
        $zem_thiseventcal = NULL;
        article_pop();
    }
    return doTag($label, $labeltag, $class) . doWrap($out, $wraptag, $break, $class, $breakclass);
}