惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tailwind CSS Blog
J
Java Code Geeks
博客园_首页
Google Online Security Blog
Google Online Security Blog
Hugging Face - Blog
Hugging Face - Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
Intezer
P
Palo Alto Networks Blog
V
Vulnerabilities – Threatpost
雷峰网
雷峰网
O
OpenAI News
SecWiki News
SecWiki News
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
N
News | PayPal Newsroom
Project Zero
Project Zero
Forbes - Security
Forbes - Security
IT之家
IT之家
A
Arctic Wolf
WordPress大学
WordPress大学
Jina AI
Jina AI
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
Google DeepMind News
Google DeepMind News
Attack and Defense Labs
Attack and Defense Labs
博客园 - 聂微东
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy International News Feed
Cloudbric
Cloudbric
G
GRAHAM CLULEY
博客园 - 叶小钗
H
Hacker News: Front Page
腾讯CDC
量子位
Help Net Security
Help Net Security
人人都是产品经理
人人都是产品经理
C
Cyber Attacks, Cyber Crime and Cyber Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
爱范儿
爱范儿
L
Lohrmann on Cybersecurity
Hacker News - Newest:
Hacker News - Newest: "LLM"
Recorded Future
Recorded Future
C
CERT Recently Published Vulnerability Notes

John Bokma's Hacking and Hiking

Failed to verify signature archive-contents.sig in Emacs Aquamacs 3.6 Hangs When Saving An Encrypted File PAR trouble How To Create a Bootable LibreELEC Installation using Mac OS Running pdflatex Using the Alpine Pandoc LaTeX Docker Image A Docker Image for Sass Timezones in Alpine Docker Containers A Tale of Three Docker Images Debugging a Perl Docker container Perl Time::Piece Unicode Issue Giving Docker Desktop for macOS a Second Chance Flashing another TP-Link TL-WDR4300 with OpenWrt firmware Rehousing two tarantulas Getting started with the Perl version of tumblelog on Ubuntu 18.04 LTS A visit to Avonturia De Vogelkelder Flashing a TP-Link TL-WDR4300 with OpenWrt firmware Mounting a VDI File in a Different VirtualBox Guest Wireless Headless Raspberry Pi - John Bokma A Matter of Time - John Bokma Hand coding an RSS 2.0 feed in Python RFC #822 and RFC #3339 dates in Perl RFC #822 and RFC #3339 dates in Python Nav Element with no Heading Rewriting CommonMark Nodes in Perl "right" this time
Hand coding an RSS 2.0 feed in Perl
John Bokma · 2019-10-10 · via John Bokma's Hacking and Hiking

October 9, 2019

One requirement I have for tumblelog is that everything the Perl version generates is identical to everything the Python version generates. This means that sometimes I have to hand code a function that is available in a library for, say Python, but works differently in a Perl library.

When I was working on adding an RSS feed to the Perl version I decided to use XML::RSS at first. But I didn't like the generated output, also because I had little to no control over it. Next I have XML::Writer a spin, but couldn't match the output of Python, using lxml.etree. So I decided to hand code both the Perl and the Python version as it's a simple feed, and XML::Writer just added a few wrapper functions.

my @MON_LIST = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my @DAY_LIST = qw( Sun Mon Tue Wed Thu Fri Sat );

sub create_rss_feed {

    my ( $days, $config ) = @_;

    my @items;
    my $todo = $config->{ days };

    for my $day ( @$days ) {

        my ( $url, $title, $description )
            = get_url_title_description( $day, $config );

        my $end_of_day = get_end_of_day( $day->{ date } );
        # RFC #822 in USA locale
        my $pub_date = $DAY_LIST[ $end_of_day->_wday() ]
            . sprintf( ', %02d ', $end_of_day->mday() )
            . $MON_LIST[ $end_of_day->_mon ]
            . $end_of_day->strftime( ' %Y %H:%M:%S %z' );

        push @items, join( '',
            '<item>',
            '<title>', escape( $title ), '</title>',
            '<link>', escape( $url ), '</link>',
            '<guid isPermaLink="true">', escape( $url ), '</guid>',
            '<pubDate>', escape( $pub_date ), '</pubDate>',
            '<description>', escape( $description ), '</description>',
            '</item>'
        );
        --$todo or last;
    }

    my $xml = join( '',
        '<?xml version="1.0" encoding="UTF-8"?>',
        '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">',
        '<channel>',
        '<title>', escape( $config->{ name } ), '</title>',
        '<link>', escape( $config->{ 'blog-url' } ), '</link>',
        '<description>', escape( $config->{ description } ),'</description>',
        '<atom:link href="', escape( $config->{ 'rss-feed-url' } ),
        '" rel="self" type="application/rss+xml" />',
        @items,
        '</channel>',
        '</rss>',
        "\n"
    );

    my $path = $config->{ 'rss-path' };
    path( "$config->{ 'output-dir' }/$path" )
        ->append_utf8( { truncate => 1 }, $xml );
    $config->{ quiet } or print "Created '$path'\n";

    return;
}

The code is quite straightforward. The calculation of the publication date is explained in RFC #822 and RFC #3339 dates in Perl.

The escape function is also hand coded to make sure its output is identical to the escape function in Python's html module:

sub escape {

    my $str = shift;

    for ( $str ) {
        s/&/&amp;/g;
        s/</&lt;/g;
        s/>/&gt;/g;
        s/"/&quot;/g;
        s/'/&#x27;/g;
    }
    return $str;
}

It uses a for loop to alias $str to $_. As the s operator defaults to $_ this saves some typing and in my opinion is more clear.

Note that a single quote is replaced with a hexadecimal code instead of &apos; for maximum compatibility, see also Character entity references in HTML 4.

If you are interested in the rest of the source code you can download it from GitHub.

Related