this file to name it for gitweb.</title>
<meta name='generator' content='cgit v1.2.3'/>
<meta name='robots' content='index, nofollow'/>
<link rel='stylesheet' type='text/css' href='/cgit-css/cgit.css'/>
<link rel='stylesheet' type='text/css' href='/cgit-local/local.css'/>
<script type='text/javascript' src='/cgit.js'></script>
<link rel='shortcut icon' href='/favicon.ico'/>
<link rel='alternate' title='Atom feed' href='https://source.jones.dk/ikiwiki-upstream/atom/IkiWiki/Plugin/aggregate.pm?h=master' type='application/atom+xml'/>
<link rel='vcs-git' href='https://source.jones.dk/ikiwiki-upstream' title='ikiwiki-upstream Git repository'/>
<link rel='vcs-git' href='user@source.jones.dk:ikiwiki-upstream' title='ikiwiki-upstream Git repository'/>
</head>
<body>
<div id='cgit'><table id='header'>
<tr>
<td class='logo' rowspan='2'><a href='/'><img src='/cgit-css/cgit.png' alt='cgit logo'/></a></td>
<td class='main'><a href='/'>index</a> : <a href='/ikiwiki-upstream/'>ikiwiki-upstream</a></td><td class='form'><form method='get'>
<input type='hidden' name='id' value='940bc51feca5be533ce2e78d4d9ea76188102cd5'/><select name='h' onchange='this.form.submit();'>
<option value='layoutgala'>layoutgala</option>
<option value='master' selected='selected'>master</option>
</select> <input type='submit' value='switch'/></form></td></tr>
<tr><td class='sub'>Unnamed repository; edit this file to name it for gitweb.</td><td class='sub right'>Jonas Smedegaard</td></tr></table>
<table class='tabs'><tr><td>
<a href='/ikiwiki-upstream/'>summary</a><a href='/ikiwiki-upstream/refs/?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>refs</a><a href='/ikiwiki-upstream/log/IkiWiki/Plugin/aggregate.pm'>log</a><a class='active' href='/ikiwiki-upstream/tree/IkiWiki/Plugin/aggregate.pm?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>tree</a><a href='/ikiwiki-upstream/commit/IkiWiki/Plugin/aggregate.pm?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>commit</a><a href='/ikiwiki-upstream/diff/IkiWiki/Plugin/aggregate.pm?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>diff</a></td><td class='form'><form class='right' method='get' action='/ikiwiki-upstream/log/IkiWiki/Plugin/aggregate.pm'>
<input type='hidden' name='id' value='940bc51feca5be533ce2e78d4d9ea76188102cd5'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/ikiwiki-upstream/tree/?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>root</a>/<a href='/ikiwiki-upstream/tree/IkiWiki?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>IkiWiki</a>/<a href='/ikiwiki-upstream/tree/IkiWiki/Plugin?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>Plugin</a>/<a href='/ikiwiki-upstream/tree/IkiWiki/Plugin/aggregate.pm?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>aggregate.pm</a></div><div class='content'>blob: 942dbbcc3e0ad69d0148382ba163869dce71c58d (<a href='/ikiwiki-upstream/plain/IkiWiki/Plugin/aggregate.pm?id=940bc51feca5be533ce2e78d4d9ea76188102cd5'>plain</a>)
<table summary='blob content' class='blob'>
<tr>
<td class='lines'><pre><code><ol class="hl">
<li id="n_1" class="hl"><span class="hl slc">#!/usr/bin/perl</span></li>
<li id="n_2" class="hl"><span class="hl slc">#&nbsp;Blog aggregation plugin.</span></li>
<li id="n_3" class="hl"><span class="hl kwa">package </span>IkiWiki<span class="hl opt">::</span>Plugin<span class="hl opt">::</span>aggregate<span class="hl opt">;</span></li>
<li id="n_4" class="hl"></li>
<li id="n_5" class="hl"><span class="hl kwa">use </span>warnings<span class="hl opt">;</span></li>
<li id="n_6" class="hl"><span class="hl kwa">use </span>strict<span class="hl opt">;</span></li>
<li id="n_7" class="hl"><span class="hl kwa">use </span>IkiWiki <span class="hl num">2.00</span><span class="hl opt">;</span></li>
<li id="n_8" class="hl"><span class="hl kwa">use </span>HTML<span class="hl opt">::</span>Parser<span class="hl opt">;</span></li>
<li id="n_9" class="hl"><span class="hl kwa">use </span>HTML<span class="hl opt">::</span>Tagset<span class="hl opt">;</span></li>
<li id="n_10" class="hl"><span class="hl kwa">use </span>HTML<span class="hl opt">::</span>Entities<span class="hl opt">;</span></li>
<li id="n_11" class="hl"><span class="hl kwa">use </span>URI<span class="hl opt">;</span></li>
<li id="n_12" class="hl"><span class="hl kwa">use </span><span class="hl kwc">open </span><span class="hl sng">qw{:utf8 :std}</span><span class="hl opt">;</span></li>
<li id="n_13" class="hl"></li>
<li id="n_14" class="hl"><span class="hl kwc">my </span><span class="hl kwb">%feeds</span><span class="hl opt">;</span></li>
<li id="n_15" class="hl"><span class="hl kwc">my </span><span class="hl kwb">%guids</span><span class="hl opt">;</span></li>
<li id="n_16" class="hl"></li>
<li id="n_17" class="hl"><span class="hl kwa">sub </span>import <span class="hl opt">{ </span><span class="hl slc">#{{{</span></li>
<li id="n_18" class="hl">    hook<span class="hl opt">(</span>type <span class="hl opt">=&gt; </span><span class="hl sng">&quot;getopt&quot;</span><span class="hl opt">, </span>id <span class="hl opt">=&gt; </span><span class="hl sng">&quot;aggregate&quot;</span><span class="hl opt">, </span>call <span class="hl opt">=&gt; </span>\<span class="hl opt">&amp;</span>getopt<span class="hl opt">);</span></li>
<li id="n_19" class="hl">    hook<span class="hl opt">(</span>type <span class="hl opt">=&gt; </span><span class="hl sng">&quot;checkconfig&quot;</span><span class="hl opt">, </span>id <span class="hl opt">=&gt; </span><span class="hl sng">&quot;aggregate&quot;</span><span class="hl opt">, </span>call <span class="hl opt">=&gt; </span>\<span class="hl opt">&amp;</span>checkconfig<span class="hl opt">);</span></li>
<li id="n_20" class="hl">    hook<span class="hl opt">(</span>type <span class="hl opt">=&gt; </span><span class="hl sng">&quot;needsbuild&quot;</span><span class="hl opt">, </span>id <span class="hl opt">=&gt; </span><span class="hl sng">&quot;aggregate&quot;</span><span class="hl opt">, </span>call <span class="hl opt">=&gt; </span>\<span class="hl opt">&amp;</span>needsbuild<span class="hl opt">);</span></li>
<li id="n_21" class="hl">    hook<span class="hl opt">(</span>type <span class="hl opt">=&gt; </span><span class="hl sng">&quot;preprocess&quot;</span><span class="hl opt">, </span>id <span class="hl opt">=&gt; </span><span class="hl sng">&quot;aggregate&quot;</span><span class="hl opt">, </span>call <span class="hl opt">=&gt; </span>\<span class="hl opt">&amp;</span>preprocess<span class="hl opt">);</span></li>
<li id="n_22" class="hl">        hook<span class="hl opt">(</span>type <span class="hl opt">=&gt; </span><span class="hl sng">&quot;delete&quot;</span><span class="hl opt">, </span>id <span class="hl opt">=&gt; </span><span class="hl sng">&quot;aggregate&quot;</span><span class="hl opt">, </span>call <span class="hl opt">=&gt; </span>\<span class="hl opt">&amp;</span><span class="hl kwc">delete</span><span class="hl opt">);</span></li>
<li id="n_23" class="hl">    hook<span class="hl opt">(</span>type <span class="hl opt">=&gt; </span><span class="hl sng">&quot;savestate&quot;</span><span class="hl opt">, </span>id <span class="hl opt">=&gt; </span><span class="hl sng">&quot;aggregate&quot;</span><span class="hl opt">, </span>call <span class="hl opt">=&gt; </span>\<span class="hl opt">&amp;</span>savestate<span class="hl opt">);</span></li>
<li id="n_24" class="hl"><span class="hl opt">} </span><span class="hl slc"># }}}</span></li>
<li id="n_25" class="hl"></li>
<li id="n_26" class="hl"><span class="hl kwa">sub </span>getopt <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_27" class="hl">        <span class="hl kwc">eval </span><span class="hl sng">q{use Getopt::Long}</span><span class="hl opt">;</span></li>
<li id="n_28" class="hl">    error<span class="hl opt">(</span><span class="hl kwb">$&#64;</span><span class="hl opt">) </span><span class="hl kwa">if </span><span class="hl kwb">$&#64;</span><span class="hl opt">;</span></li>
<li id="n_29" class="hl">        Getopt<span class="hl opt">::</span>Long<span class="hl opt">::</span>Configure<span class="hl opt">(</span><span class="hl sng">&#39;pass_through&#39;</span><span class="hl opt">);</span></li>
<li id="n_30" class="hl">        GetOptions<span class="hl opt">(</span><span class="hl sng">&quot;aggregate&quot;</span> <span class="hl opt">=&gt; </span>\<span class="hl kwb">$config</span><span class="hl opt">{</span>aggregate<span class="hl opt">});</span></li>
<li id="n_31" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_32" class="hl"></li>
<li id="n_33" class="hl"><span class="hl kwa">sub </span>checkconfig <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_34" class="hl">    <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$config</span><span class="hl opt">{</span>aggregate<span class="hl opt">} &amp;&amp; ! (</span><span class="hl kwb">$config</span><span class="hl opt">{</span>post_commit<span class="hl opt">} &amp;&amp; </span></li>
<li id="n_35" class="hl">                                 IkiWiki<span class="hl opt">::</span>commit_hook_enabled<span class="hl opt">())) {</span></li>
<li id="n_36" class="hl">        <span class="hl slc"># See if any feeds need aggregation.</span></li>
<li id="n_37" class="hl">        loadstate<span class="hl opt">();</span></li>
<li id="n_38" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">&#64;feeds</span><span class="hl opt">=</span>needsaggregate<span class="hl opt">();</span></li>
<li id="n_39" class="hl">        <span class="hl kwa">return unless </span><span class="hl kwb">&#64;feeds</span><span class="hl opt">;</span></li>
<li id="n_40" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span>lockaggregate<span class="hl opt">()) {</span></li>
<li id="n_41" class="hl">            debug<span class="hl opt">(</span><span class="hl sng">&quot;an aggregation process is already running&quot;</span><span class="hl opt">);</span></li>
<li id="n_42" class="hl">            <span class="hl kwa">return</span><span class="hl opt">;</span></li>
<li id="n_43" class="hl">        <span class="hl opt">}</span></li>
<li id="n_44" class="hl">        <span class="hl slc"># force a later rebuild of source pages</span></li>
<li id="n_45" class="hl">        <span class="hl kwb">$IkiWiki</span><span class="hl opt">::</span>forcerebuild<span class="hl opt">{</span><span class="hl kwb">$_</span><span class="hl opt">-&gt;{</span>sourcepage<span class="hl opt">}}=</span><span class="hl num">1</span></li>
<li id="n_46" class="hl">            <span class="hl kwa">foreach </span><span class="hl kwb">&#64;feeds</span><span class="hl opt">;</span></li>
<li id="n_47" class="hl"></li>
<li id="n_48" class="hl">        <span class="hl slc"># Fork a child process to handle the aggregation.</span></li>
<li id="n_49" class="hl">        <span class="hl slc"># The parent process will then handle building the</span></li>
<li id="n_50" class="hl">        <span class="hl slc"># result. This avoids messy code to clear state</span></li>
<li id="n_51" class="hl">        <span class="hl slc"># accumulated while aggregating.</span></li>
<li id="n_52" class="hl">        <span class="hl kwc">defined</span><span class="hl opt">(</span><span class="hl kwc">my </span><span class="hl kwb">$pid </span><span class="hl opt">= </span><span class="hl kwc">fork</span><span class="hl opt">) </span><span class="hl kwc">or </span>error<span class="hl opt">(</span><span class="hl sng">&quot;Can&#39;t fork: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">);</span></li>
<li id="n_53" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwb">$pid</span><span class="hl opt">) {</span></li>
<li id="n_54" class="hl">            IkiWiki<span class="hl opt">::</span>loadindex<span class="hl opt">();</span></li>
<li id="n_55" class="hl"></li>
<li id="n_56" class="hl">            <span class="hl slc"># Aggregation happens without the main wiki lock</span></li>
<li id="n_57" class="hl">            <span class="hl slc"># being held. This allows editing pages etc while</span></li>
<li id="n_58" class="hl">            <span class="hl slc"># aggregation is running.</span></li>
<li id="n_59" class="hl">            aggregate<span class="hl opt">(</span><span class="hl kwb">&#64;feeds</span><span class="hl opt">);</span></li>
<li id="n_60" class="hl"></li>
<li id="n_61" class="hl">            IkiWiki<span class="hl opt">::</span>lockwiki<span class="hl opt">;</span></li>
<li id="n_62" class="hl">            <span class="hl slc"># Merge changes, since aggregation state may have</span></li>
<li id="n_63" class="hl">            <span class="hl slc"># changed on disk while the aggregation was happening.</span></li>
<li id="n_64" class="hl">            mergestate<span class="hl opt">();</span></li>
<li id="n_65" class="hl">            expire<span class="hl opt">();</span></li>
<li id="n_66" class="hl">            savestate<span class="hl opt">();</span></li>
<li id="n_67" class="hl">            IkiWiki<span class="hl opt">::</span>unlockwiki<span class="hl opt">;</span></li>
<li id="n_68" class="hl">            <span class="hl kwa">exit </span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_69" class="hl">        <span class="hl opt">}</span></li>
<li id="n_70" class="hl">        <span class="hl kwc">waitpid</span><span class="hl opt">(</span><span class="hl kwb">$pid</span><span class="hl opt">,</span><span class="hl num">0</span><span class="hl opt">);</span></li>
<li id="n_71" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$?</span><span class="hl opt">) {</span></li>
<li id="n_72" class="hl">            error <span class="hl sng">&quot;aggregation failed with code </span><span class="hl ipl">$?</span><span class="hl sng">&quot;</span><span class="hl opt">;</span></li>
<li id="n_73" class="hl">        <span class="hl opt">}</span></li>
<li id="n_74" class="hl"></li>
<li id="n_75" class="hl">        clearstate<span class="hl opt">();</span></li>
<li id="n_76" class="hl">        unlockaggregate<span class="hl opt">();</span></li>
<li id="n_77" class="hl">    <span class="hl opt">}</span></li>
<li id="n_78" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_79" class="hl"></li>
<li id="n_80" class="hl"><span class="hl kwa">sub </span>needsbuild <span class="hl opt">(&#64;) { </span><span class="hl slc">#{{{</span></li>
<li id="n_81" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$needsbuild</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_82" class="hl">    </li>
<li id="n_83" class="hl">    loadstate<span class="hl opt">();</span></li>
<li id="n_84" class="hl"></li>
<li id="n_85" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$feed </span><span class="hl opt">(</span><span class="hl kwc">values </span><span class="hl kwb">%feeds</span><span class="hl opt">) {</span></li>
<li id="n_86" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$pagesources</span><span class="hl opt">{</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>sourcepage<span class="hl opt">}} &amp;&amp; </span></li>
<li id="n_87" class="hl">            <span class="hl kwc">grep </span><span class="hl opt">{ </span><span class="hl kwb">$_ </span><span class="hl kwc">eq </span><span class="hl kwb">$pagesources</span><span class="hl opt">{</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>sourcepage<span class="hl opt">}} } </span><span class="hl kwb">&#64;$needsbuild</span><span class="hl opt">) {</span></li>
<li id="n_88" class="hl">            <span class="hl slc"># Mark all feeds originating on this page as </span></li>
<li id="n_89" class="hl">            <span class="hl slc"># not yet seen; preprocess will unmark those that</span></li>
<li id="n_90" class="hl">            <span class="hl slc"># still exist.</span></li>
<li id="n_91" class="hl">            markunseen<span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>sourcepage<span class="hl opt">});</span></li>
<li id="n_92" class="hl">        <span class="hl opt">}</span></li>
<li id="n_93" class="hl">    <span class="hl opt">}</span></li>
<li id="n_94" class="hl"><span class="hl opt">} </span><span class="hl slc"># }}}</span></li>
<li id="n_95" class="hl"></li>
<li id="n_96" class="hl"><span class="hl kwa">sub </span>preprocess <span class="hl opt">(&#64;) { </span><span class="hl slc">#{{{</span></li>
<li id="n_97" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">%params</span><span class="hl opt">=</span><span class="hl kwb">&#64;_</span><span class="hl opt">;</span></li>
<li id="n_98" class="hl"></li>
<li id="n_99" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$required </span><span class="hl opt">(</span><span class="hl sng">qw{name url}</span><span class="hl opt">) {</span></li>
<li id="n_100" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwc">exists </span><span class="hl kwb">$params</span><span class="hl opt">{</span><span class="hl kwb">$required</span><span class="hl opt">}) {</span></li>
<li id="n_101" class="hl">            <span class="hl kwa">return </span><span class="hl sng">&quot;[[aggregate &quot;</span><span class="hl opt">.</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;missing </span><span class="hl ipl">%s </span><span class="hl sng">parameter&quot;</span><span class="hl opt">), </span><span class="hl kwb">$required</span><span class="hl opt">).</span><span class="hl sng">&quot;]]&quot;</span><span class="hl opt">;</span></li>
<li id="n_102" class="hl">        <span class="hl opt">}</span></li>
<li id="n_103" class="hl">    <span class="hl opt">}</span></li>
<li id="n_104" class="hl"></li>
<li id="n_105" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$feed</span><span class="hl opt">={};</span></li>
<li id="n_106" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$name</span><span class="hl opt">=</span><span class="hl kwb">$params</span><span class="hl opt">{</span>name<span class="hl opt">};</span></li>
<li id="n_107" class="hl">    <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">}) {</span></li>
<li id="n_108" class="hl">        <span class="hl kwb">$feed</span><span class="hl opt">=</span><span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">};</span></li>
<li id="n_109" class="hl">    <span class="hl opt">}</span></li>
<li id="n_110" class="hl">    <span class="hl kwa">else </span><span class="hl opt">{</span></li>
<li id="n_111" class="hl">        <span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">}=</span><span class="hl kwb">$feed</span><span class="hl opt">;</span></li>
<li id="n_112" class="hl">    <span class="hl opt">}</span></li>
<li id="n_113" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">}=</span><span class="hl kwb">$name</span><span class="hl opt">;</span></li>
<li id="n_114" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>sourcepage<span class="hl opt">}=</span><span class="hl kwb">$params</span><span class="hl opt">{</span>page<span class="hl opt">};</span></li>
<li id="n_115" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>url<span class="hl opt">}=</span><span class="hl kwb">$params</span><span class="hl opt">{</span>url<span class="hl opt">};</span></li>
<li id="n_116" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$dir</span><span class="hl opt">=</span><span class="hl kwc">exists </span><span class="hl kwb">$params</span><span class="hl opt">{</span>dir<span class="hl opt">} ? </span><span class="hl kwb">$params</span><span class="hl opt">{</span>dir<span class="hl opt">} : </span><span class="hl kwb">$params</span><span class="hl opt">{</span>page<span class="hl opt">}.</span><span class="hl sng">&quot;/&quot;</span><span class="hl opt">.</span>IkiWiki<span class="hl opt">::</span>titlepage<span class="hl opt">(</span><span class="hl kwb">$params</span><span class="hl opt">{</span>name<span class="hl opt">});</span></li>
<li id="n_117" class="hl">    <span class="hl kwb">$dir</span><span class="hl opt">=~</span><span class="hl kwd">s/^\/+/</span><span class="hl opt">/;</span></li>
<li id="n_118" class="hl">    <span class="hl opt">(</span><span class="hl kwb">$dir</span><span class="hl opt">)=</span><span class="hl kwb">$dir</span><span class="hl opt">=~</span><span class="hl kwd">/$config{wiki_file_regexp}/</span><span class="hl opt">;</span></li>
<li id="n_119" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>dir<span class="hl opt">}=</span><span class="hl kwb">$dir</span><span class="hl opt">;</span></li>
<li id="n_120" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>feedurl<span class="hl opt">}=</span><span class="hl kwc">defined </span><span class="hl kwb">$params</span><span class="hl opt">{</span>feedurl<span class="hl opt">} ? </span><span class="hl kwb">$params</span><span class="hl opt">{</span>feedurl<span class="hl opt">} : </span><span class="hl sng">&quot;&quot;</span><span class="hl opt">;</span></li>
<li id="n_121" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>updateinterval<span class="hl opt">}=</span><span class="hl kwc">defined </span><span class="hl kwb">$params</span><span class="hl opt">{</span>updateinterval<span class="hl opt">} ? </span><span class="hl kwb">$params</span><span class="hl opt">{</span>updateinterval<span class="hl opt">} * </span><span class="hl num">60 </span><span class="hl opt">: </span><span class="hl num">15 </span><span class="hl opt">* </span><span class="hl num">60</span><span class="hl opt">;</span></li>
<li id="n_122" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expireage<span class="hl opt">}=</span><span class="hl kwc">defined </span><span class="hl kwb">$params</span><span class="hl opt">{</span>expireage<span class="hl opt">} ? </span><span class="hl kwb">$params</span><span class="hl opt">{</span>expireage<span class="hl opt">} : </span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_123" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expirecount<span class="hl opt">}=</span><span class="hl kwc">defined </span><span class="hl kwb">$params</span><span class="hl opt">{</span>expirecount<span class="hl opt">} ? </span><span class="hl kwb">$params</span><span class="hl opt">{</span>expirecount<span class="hl opt">} : </span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_124" class="hl">    <span class="hl kwc">delete </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>unseen<span class="hl opt">};</span></li>
<li id="n_125" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>lastupdate<span class="hl opt">}=</span><span class="hl num">0 </span><span class="hl kwa">unless </span><span class="hl kwc">defined </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>lastupdate<span class="hl opt">};</span></li>
<li id="n_126" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>numposts<span class="hl opt">}=</span><span class="hl num">0 </span><span class="hl kwa">unless </span><span class="hl kwc">defined </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>numposts<span class="hl opt">};</span></li>
<li id="n_127" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>newposts<span class="hl opt">}=</span><span class="hl num">0 </span><span class="hl kwa">unless </span><span class="hl kwc">defined </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>newposts<span class="hl opt">};</span></li>
<li id="n_128" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}=</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;new feed&quot;</span><span class="hl opt">) </span><span class="hl kwa">unless </span><span class="hl kwc">defined </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">};</span></li>
<li id="n_129" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">}=</span><span class="hl num">0 </span><span class="hl kwa">unless </span><span class="hl kwc">defined </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">};</span></li>
<li id="n_130" class="hl">    <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>tags<span class="hl opt">}=[];</span></li>
<li id="n_131" class="hl">    <span class="hl kwa">while </span><span class="hl opt">(</span><span class="hl kwb">&#64;_</span><span class="hl opt">) {</span></li>
<li id="n_132" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$key</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_133" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$value</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_134" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$key </span><span class="hl kwc">eq </span><span class="hl sng">&#39;tag&#39;</span><span class="hl opt">) {</span></li>
<li id="n_135" class="hl">            <span class="hl kwc">push </span><span class="hl opt">&#64;{</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>tags<span class="hl opt">}}, </span><span class="hl kwb">$value</span><span class="hl opt">;</span></li>
<li id="n_136" class="hl">        <span class="hl opt">}</span></li>
<li id="n_137" class="hl">    <span class="hl opt">}</span></li>
<li id="n_138" class="hl"></li>
<li id="n_139" class="hl">    <span class="hl kwa">return </span><span class="hl sng">&quot;&lt;a href=</span><span class="hl esc">\&quot;</span><span class="hl sng">&quot;</span><span class="hl opt">.</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>url<span class="hl opt">}.</span><span class="hl sng">&quot;</span><span class="hl esc">\&quot;</span><span class="hl sng">&gt;&quot;</span><span class="hl opt">.</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">}.</span><span class="hl sng">&quot;&lt;/a&gt;: &quot;</span><span class="hl opt">.</span></li>
<li id="n_140" class="hl">           <span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">} ? </span><span class="hl sng">&quot;&lt;em&gt;&quot;</span> <span class="hl opt">: </span><span class="hl sng">&quot;&quot;</span><span class="hl opt">).</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}.</span></li>
<li id="n_141" class="hl">           <span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">} ? </span><span class="hl sng">&quot;&lt;/em&gt;&quot;</span> <span class="hl opt">: </span><span class="hl sng">&quot;&quot;</span><span class="hl opt">).</span></li>
<li id="n_142" class="hl">           <span class="hl sng">&quot; (&quot;</span><span class="hl opt">.</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>numposts<span class="hl opt">}.</span><span class="hl sng">&quot; &quot;</span><span class="hl opt">.</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;posts&quot;</span><span class="hl opt">).</span></li>
<li id="n_143" class="hl">           <span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>newposts<span class="hl opt">} ? </span><span class="hl sng">&quot;; &quot;</span><span class="hl opt">.</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>newposts<span class="hl opt">}.</span></li>
<li id="n_144" class="hl">                                <span class="hl sng">&quot; &quot;</span><span class="hl opt">.</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;new&quot;</span><span class="hl opt">) : </span><span class="hl sng">&quot;&quot;</span><span class="hl opt">).</span></li>
<li id="n_145" class="hl">           <span class="hl sng">&quot;)&quot;</span><span class="hl opt">;</span></li>
<li id="n_146" class="hl"><span class="hl opt">} </span><span class="hl slc"># }}}</span></li>
<li id="n_147" class="hl"></li>
<li id="n_148" class="hl"><span class="hl kwa">sub </span><span class="hl kwc">delete </span><span class="hl opt">(&#64;) { </span><span class="hl slc">#{{{</span></li>
<li id="n_149" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">&#64;files</span><span class="hl opt">=</span><span class="hl kwb">&#64;_</span><span class="hl opt">;</span></li>
<li id="n_150" class="hl"></li>
<li id="n_151" class="hl">    <span class="hl slc"># Remove feed data for removed pages.</span></li>
<li id="n_152" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$file </span><span class="hl opt">(</span><span class="hl kwb">&#64;files</span><span class="hl opt">) {</span></li>
<li id="n_153" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$page</span><span class="hl opt">=</span>pagename<span class="hl opt">(</span><span class="hl kwb">$file</span><span class="hl opt">);</span></li>
<li id="n_154" class="hl">        markunseen<span class="hl opt">(</span><span class="hl kwb">$page</span><span class="hl opt">);</span></li>
<li id="n_155" class="hl">    <span class="hl opt">}</span></li>
<li id="n_156" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_157" class="hl"></li>
<li id="n_158" class="hl"><span class="hl kwa">sub </span>markunseen <span class="hl opt">($) { </span><span class="hl slc">#{{{</span></li>
<li id="n_159" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$page</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_160" class="hl"></li>
<li id="n_161" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$id </span><span class="hl opt">(</span><span class="hl kwc">keys </span><span class="hl kwb">%feeds</span><span class="hl opt">) {</span></li>
<li id="n_162" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$id</span><span class="hl opt">}-&gt;{</span>sourcepage<span class="hl opt">} </span><span class="hl kwc">eq </span><span class="hl kwb">$page</span><span class="hl opt">) {</span></li>
<li id="n_163" class="hl">            <span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$id</span><span class="hl opt">}-&gt;{</span>unseen<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_164" class="hl">        <span class="hl opt">}</span></li>
<li id="n_165" class="hl">    <span class="hl opt">}</span></li>
<li id="n_166" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_167" class="hl"></li>
<li id="n_168" class="hl"><span class="hl kwc">my </span><span class="hl kwb">$state_loaded</span><span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_169" class="hl"></li>
<li id="n_170" class="hl"><span class="hl kwa">sub </span>loadstate <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_171" class="hl">    <span class="hl kwa">return if </span><span class="hl kwb">$state_loaded</span><span class="hl opt">;</span></li>
<li id="n_172" class="hl">    <span class="hl kwb">$state_loaded</span><span class="hl opt">=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_173" class="hl">    <span class="hl kwa">if </span><span class="hl opt">(-</span>e <span class="hl sng">&quot;</span><span class="hl ipl">$config</span><span class="hl sng">{wikistatedir}/aggregate&quot;</span><span class="hl opt">) {</span></li>
<li id="n_174" class="hl">        <span class="hl kwc">open</span><span class="hl opt">(</span>IN<span class="hl opt">, </span><span class="hl sng">&quot;</span><span class="hl ipl">$config</span><span class="hl sng">{wikistatedir}/aggregate&quot;</span><span class="hl opt">) ||</span></li>
<li id="n_175" class="hl">            <span class="hl kwc">die </span><span class="hl sng">&quot;</span><span class="hl ipl">$config</span><span class="hl sng">{wikistatedir}/aggregate: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">;</span></li>
<li id="n_176" class="hl">        <span class="hl kwa">while </span><span class="hl opt">(&lt;</span>IN<span class="hl opt">&gt;) {</span></li>
<li id="n_177" class="hl">            <span class="hl kwb">$_</span><span class="hl opt">=</span>IkiWiki<span class="hl opt">::</span>possibly_foolish_untaint<span class="hl opt">(</span><span class="hl kwb">$_</span><span class="hl opt">);</span></li>
<li id="n_178" class="hl">            <span class="hl kwc">chomp</span><span class="hl opt">;</span></li>
<li id="n_179" class="hl">            <span class="hl kwc">my </span><span class="hl kwb">$data</span><span class="hl opt">={};</span></li>
<li id="n_180" class="hl">            <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$i </span><span class="hl opt">(</span><span class="hl kwc">split</span><span class="hl opt">(</span><span class="hl kwd">/ /</span><span class="hl opt">, </span><span class="hl kwb">$_</span><span class="hl opt">)) {</span></li>
<li id="n_181" class="hl">                <span class="hl kwc">my </span><span class="hl opt">(</span><span class="hl kwb">$field</span><span class="hl opt">, </span><span class="hl kwb">$val</span><span class="hl opt">)=</span><span class="hl kwc">split</span><span class="hl opt">(</span><span class="hl kwd">/=/</span><span class="hl opt">, </span><span class="hl kwb">$i</span><span class="hl opt">, </span><span class="hl num">2</span><span class="hl opt">);</span></li>
<li id="n_182" class="hl">                <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;name&quot;</span> <span class="hl opt">|| </span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;feed&quot;</span> <span class="hl opt">||</span></li>
<li id="n_183" class="hl">                    <span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;guid&quot;</span> <span class="hl opt">|| </span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;message&quot;</span><span class="hl opt">) {</span></li>
<li id="n_184" class="hl">                    <span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span><span class="hl kwb">$field</span><span class="hl opt">}=</span>decode_entities<span class="hl opt">(</span><span class="hl kwb">$val</span><span class="hl opt">, </span><span class="hl sng">&quot; </span><span class="hl esc">\t\n</span><span class="hl sng">&quot;</span><span class="hl opt">);</span></li>
<li id="n_185" class="hl">                <span class="hl opt">}</span></li>
<li id="n_186" class="hl">                <span class="hl kwa">elsif </span><span class="hl opt">(</span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;tag&quot;</span><span class="hl opt">) {</span></li>
<li id="n_187" class="hl">                    <span class="hl kwc">push </span><span class="hl opt">&#64;{</span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span>tags<span class="hl opt">}}, </span><span class="hl kwb">$val</span><span class="hl opt">;</span></li>
<li id="n_188" class="hl">                <span class="hl opt">}</span></li>
<li id="n_189" class="hl">                <span class="hl kwa">else </span><span class="hl opt">{</span></li>
<li id="n_190" class="hl">                    <span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span><span class="hl kwb">$field</span><span class="hl opt">}=</span><span class="hl kwb">$val</span><span class="hl opt">;</span></li>
<li id="n_191" class="hl">                <span class="hl opt">}</span></li>
<li id="n_192" class="hl">            <span class="hl opt">}</span></li>
<li id="n_193" class="hl">            </li>
<li id="n_194" class="hl">            <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">}) {</span></li>
<li id="n_195" class="hl">                <span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">}}=</span><span class="hl kwb">$data</span><span class="hl opt">;</span></li>
<li id="n_196" class="hl">            <span class="hl opt">}</span></li>
<li id="n_197" class="hl">            <span class="hl kwa">elsif </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span>guid<span class="hl opt">}) {</span></li>
<li id="n_198" class="hl">                <span class="hl kwb">$guids</span><span class="hl opt">{</span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span>guid<span class="hl opt">}}=</span><span class="hl kwb">$data</span><span class="hl opt">;</span></li>
<li id="n_199" class="hl">            <span class="hl opt">}</span></li>
<li id="n_200" class="hl">        <span class="hl opt">}</span></li>
<li id="n_201" class="hl"></li>
<li id="n_202" class="hl">        <span class="hl kwc">close </span>IN<span class="hl opt">;</span></li>
<li id="n_203" class="hl">    <span class="hl opt">}</span></li>
<li id="n_204" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_205" class="hl"></li>
<li id="n_206" class="hl"><span class="hl kwa">sub </span>savestate <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_207" class="hl">    <span class="hl kwa">return unless </span><span class="hl kwb">$state_loaded</span><span class="hl opt">;</span></li>
<li id="n_208" class="hl">    garbage_collect<span class="hl opt">();</span></li>
<li id="n_209" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$newfile</span><span class="hl opt">=</span><span class="hl sng">&quot;</span><span class="hl ipl">$config</span><span class="hl sng">{wikistatedir}/aggregate.new&quot;</span><span class="hl opt">;</span></li>
<li id="n_210" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$cleanup </span><span class="hl opt">= </span><span class="hl kwa">sub </span><span class="hl opt">{ </span><span class="hl kwc">unlink</span><span class="hl opt">(</span><span class="hl kwb">$newfile</span><span class="hl opt">) };</span></li>
<li id="n_211" class="hl">    <span class="hl kwc">open </span><span class="hl opt">(</span>OUT<span class="hl opt">, </span><span class="hl sng">&quot;&gt;</span><span class="hl ipl">$newfile</span><span class="hl sng">&quot;</span><span class="hl opt">) || </span>error<span class="hl opt">(</span><span class="hl sng">&quot;open </span><span class="hl ipl">$newfile</span><span class="hl sng">: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">, </span><span class="hl kwb">$cleanup</span><span class="hl opt">);</span></li>
<li id="n_212" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$data </span><span class="hl opt">(</span><span class="hl kwc">values </span><span class="hl kwb">%feeds</span><span class="hl opt">, </span><span class="hl kwc">values </span><span class="hl kwb">%guids</span><span class="hl opt">) {</span></li>
<li id="n_213" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">&#64;line</span><span class="hl opt">;</span></li>
<li id="n_214" class="hl">        <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$field </span><span class="hl opt">(</span><span class="hl kwc">keys </span><span class="hl kwb">%$data</span><span class="hl opt">) {</span></li>
<li id="n_215" class="hl">            <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;name&quot;</span> <span class="hl opt">|| </span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;feed&quot;</span> <span class="hl opt">||</span></li>
<li id="n_216" class="hl">                <span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;guid&quot;</span> <span class="hl opt">|| </span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;message&quot;</span><span class="hl opt">) {</span></li>
<li id="n_217" class="hl">                <span class="hl kwc">push </span><span class="hl kwb">&#64;line</span><span class="hl opt">, </span><span class="hl sng">&quot;</span><span class="hl ipl">$field</span><span class="hl sng">=&quot;</span><span class="hl opt">.</span>encode_entities<span class="hl opt">(</span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span><span class="hl kwb">$field</span><span class="hl opt">}, </span><span class="hl sng">&quot; </span><span class="hl esc">\t\n</span><span class="hl sng">&quot;</span><span class="hl opt">);</span></li>
<li id="n_218" class="hl">            <span class="hl opt">}</span></li>
<li id="n_219" class="hl">            <span class="hl kwa">elsif </span><span class="hl opt">(</span><span class="hl kwb">$field </span><span class="hl kwc">eq </span><span class="hl sng">&quot;tags&quot;</span><span class="hl opt">) {</span></li>
<li id="n_220" class="hl">                <span class="hl kwc">push </span><span class="hl kwb">&#64;line</span><span class="hl opt">, </span><span class="hl sng">&quot;tag=</span><span class="hl ipl">$_</span><span class="hl sng">&quot;</span> <span class="hl kwa">foreach </span><span class="hl opt">&#64;{</span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span>tags<span class="hl opt">}};</span></li>
<li id="n_221" class="hl">            <span class="hl opt">}</span></li>
<li id="n_222" class="hl">            <span class="hl kwa">else </span><span class="hl opt">{</span></li>
<li id="n_223" class="hl">                <span class="hl kwc">push </span><span class="hl kwb">&#64;line</span><span class="hl opt">, </span><span class="hl sng">&quot;</span><span class="hl ipl">$field</span><span class="hl sng">=&quot;</span><span class="hl opt">.</span><span class="hl kwb">$data</span><span class="hl opt">-&gt;{</span><span class="hl kwb">$field</span><span class="hl opt">};</span></li>
<li id="n_224" class="hl">            <span class="hl opt">}</span></li>
<li id="n_225" class="hl">        <span class="hl opt">}</span></li>
<li id="n_226" class="hl">        <span class="hl kwc">print </span>OUT <span class="hl kwc">join</span><span class="hl opt">(</span><span class="hl sng">&quot; &quot;</span><span class="hl opt">, </span><span class="hl kwb">&#64;line</span><span class="hl opt">).</span><span class="hl sng">&quot;</span><span class="hl esc">\n</span><span class="hl sng">&quot;</span> <span class="hl opt">|| </span>error<span class="hl opt">(</span><span class="hl sng">&quot;write </span><span class="hl ipl">$newfile</span><span class="hl sng">: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">, </span><span class="hl kwb">$cleanup</span><span class="hl opt">);</span></li>
<li id="n_227" class="hl">    <span class="hl opt">}</span></li>
<li id="n_228" class="hl">    <span class="hl kwc">close </span>OUT <span class="hl opt">|| </span>error<span class="hl opt">(</span><span class="hl sng">&quot;save </span><span class="hl ipl">$newfile</span><span class="hl sng">: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">, </span><span class="hl kwb">$cleanup</span><span class="hl opt">);</span></li>
<li id="n_229" class="hl">    <span class="hl kwc">rename</span><span class="hl opt">(</span><span class="hl kwb">$newfile</span><span class="hl opt">, </span><span class="hl sng">&quot;</span><span class="hl ipl">$config</span><span class="hl sng">{wikistatedir}/aggregate&quot;</span><span class="hl opt">) ||</span></li>
<li id="n_230" class="hl">        error<span class="hl opt">(</span><span class="hl sng">&quot;rename </span><span class="hl ipl">$newfile</span><span class="hl sng">: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">, </span><span class="hl kwb">$cleanup</span><span class="hl opt">);</span></li>
<li id="n_231" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_232" class="hl"></li>
<li id="n_233" class="hl"><span class="hl kwa">sub </span>garbage_collect <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_234" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$name </span><span class="hl opt">(</span><span class="hl kwc">keys </span><span class="hl kwb">%feeds</span><span class="hl opt">) {</span></li>
<li id="n_235" class="hl">        <span class="hl slc"># remove any feeds that were not seen while building the pages</span></li>
<li id="n_236" class="hl">        <span class="hl slc"># that used to contain them</span></li>
<li id="n_237" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">}-&gt;{</span>unseen<span class="hl opt">}) {</span></li>
<li id="n_238" class="hl">            <span class="hl kwc">delete </span><span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">};</span></li>
<li id="n_239" class="hl">        <span class="hl opt">}</span></li>
<li id="n_240" class="hl">    <span class="hl opt">}</span></li>
<li id="n_241" class="hl"></li>
<li id="n_242" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$guid </span><span class="hl opt">(</span><span class="hl kwc">values </span><span class="hl kwb">%guids</span><span class="hl opt">) {</span></li>
<li id="n_243" class="hl">        <span class="hl slc"># any guid whose feed is gone should be removed</span></li>
<li id="n_244" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwc">exists </span><span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>feed<span class="hl opt">}}) {</span></li>
<li id="n_245" class="hl">            <span class="hl kwc">unlink </span>pagefile<span class="hl opt">(</span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">})</span></li>
<li id="n_246" class="hl">                <span class="hl kwa">if </span><span class="hl kwc">exists </span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">};</span></li>
<li id="n_247" class="hl">            <span class="hl kwc">delete </span><span class="hl kwb">$guids</span><span class="hl opt">{</span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>guid<span class="hl opt">}};</span></li>
<li id="n_248" class="hl">        <span class="hl opt">}</span></li>
<li id="n_249" class="hl">        <span class="hl slc"># handle expired guids</span></li>
<li id="n_250" class="hl">        <span class="hl kwa">elsif </span><span class="hl opt">(</span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>expired<span class="hl opt">} &amp;&amp; </span><span class="hl kwc">exists </span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}) {</span></li>
<li id="n_251" class="hl">            <span class="hl kwc">unlink </span>pagefile<span class="hl opt">(</span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">});</span></li>
<li id="n_252" class="hl">            <span class="hl kwc">delete </span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">};</span></li>
<li id="n_253" class="hl">            <span class="hl kwc">delete </span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>md5<span class="hl opt">};</span></li>
<li id="n_254" class="hl">        <span class="hl opt">}</span></li>
<li id="n_255" class="hl">    <span class="hl opt">}</span></li>
<li id="n_256" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_257" class="hl"></li>
<li id="n_258" class="hl"><span class="hl kwa">sub </span>mergestate <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_259" class="hl">    <span class="hl slc"># Load the current state in from disk, and merge into it</span></li>
<li id="n_260" class="hl">    <span class="hl slc"># values from the state in memory that might have changed</span></li>
<li id="n_261" class="hl">    <span class="hl slc"># during aggregation.</span></li>
<li id="n_262" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">%myfeeds</span><span class="hl opt">=</span><span class="hl kwb">%feeds</span><span class="hl opt">;</span></li>
<li id="n_263" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">%myguids</span><span class="hl opt">=</span><span class="hl kwb">%guids</span><span class="hl opt">;</span></li>
<li id="n_264" class="hl">    clearstate<span class="hl opt">();</span></li>
<li id="n_265" class="hl">    loadstate<span class="hl opt">();</span></li>
<li id="n_266" class="hl"></li>
<li id="n_267" class="hl">    <span class="hl slc"># All that can change in feed state during aggregation is a few</span></li>
<li id="n_268" class="hl">    <span class="hl slc"># fields.</span></li>
<li id="n_269" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$name </span><span class="hl opt">(</span><span class="hl kwc">keys </span><span class="hl kwb">%myfeeds</span><span class="hl opt">) {</span></li>
<li id="n_270" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">}) {</span></li>
<li id="n_271" class="hl">            <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$field </span><span class="hl opt">(</span><span class="hl sng">qw{message lastupdate numposts</span></li>
<li id="n_272" class="hl"><span class="hl sng">                                  newposts error}</span><span class="hl opt">) {</span></li>
<li id="n_273" class="hl">                <span class="hl kwb">$feeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">}-&gt;{</span><span class="hl kwb">$field</span><span class="hl opt">}=</span><span class="hl kwb">$myfeeds</span><span class="hl opt">{</span><span class="hl kwb">$name</span><span class="hl opt">}-&gt;{</span><span class="hl kwb">$field</span><span class="hl opt">};</span></li>
<li id="n_274" class="hl">            <span class="hl opt">}</span></li>
<li id="n_275" class="hl">        <span class="hl opt">}</span></li>
<li id="n_276" class="hl">    <span class="hl opt">}</span></li>
<li id="n_277" class="hl"></li>
<li id="n_278" class="hl">    <span class="hl slc"># New guids can be created during aggregation.</span></li>
<li id="n_279" class="hl">    <span class="hl slc"># It&#39;s also possible that guids were removed from the on-disk state</span></li>
<li id="n_280" class="hl">    <span class="hl slc"># while the aggregation was in process. That would only happen if</span></li>
<li id="n_281" class="hl">    <span class="hl slc"># their feed was also removed, so any removed guids added back here</span></li>
<li id="n_282" class="hl">    <span class="hl slc"># will be garbage collected later.</span></li>
<li id="n_283" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$guid </span><span class="hl opt">(</span><span class="hl kwc">keys </span><span class="hl kwb">%myguids</span><span class="hl opt">) {</span></li>
<li id="n_284" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwc">exists </span><span class="hl kwb">$guids</span><span class="hl opt">{</span><span class="hl kwb">$guid</span><span class="hl opt">}) {</span></li>
<li id="n_285" class="hl">            <span class="hl kwb">$guids</span><span class="hl opt">{</span><span class="hl kwb">$guid</span><span class="hl opt">}=</span><span class="hl kwb">$myguids</span><span class="hl opt">{</span><span class="hl kwb">$guid</span><span class="hl opt">};</span></li>
<li id="n_286" class="hl">        <span class="hl opt">}</span></li>
<li id="n_287" class="hl">    <span class="hl opt">}</span></li>
<li id="n_288" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_289" class="hl"></li>
<li id="n_290" class="hl"><span class="hl kwa">sub </span>clearstate <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_291" class="hl">    <span class="hl kwb">%feeds</span><span class="hl opt">=();</span></li>
<li id="n_292" class="hl">    <span class="hl kwb">%guids</span><span class="hl opt">=();</span></li>
<li id="n_293" class="hl">    <span class="hl kwb">$state_loaded</span><span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_294" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_295" class="hl"></li>
<li id="n_296" class="hl"><span class="hl kwa">sub </span>expire <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_297" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$feed </span><span class="hl opt">(</span><span class="hl kwc">values </span><span class="hl kwb">%feeds</span><span class="hl opt">) {</span></li>
<li id="n_298" class="hl">        <span class="hl kwa">next unless </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expireage<span class="hl opt">} || </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expirecount<span class="hl opt">};</span></li>
<li id="n_299" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$count</span><span class="hl opt">=</span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_300" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">%seen</span><span class="hl opt">;</span></li>
<li id="n_301" class="hl">        <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$item </span><span class="hl opt">(</span><span class="hl kwc">sort </span><span class="hl opt">{ </span><span class="hl kwb">$IkiWiki</span><span class="hl opt">::</span>pagectime<span class="hl opt">{</span><span class="hl kwb">$b</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}} &lt;=&gt; </span><span class="hl kwb">$IkiWiki</span><span class="hl opt">::</span>pagectime<span class="hl opt">{</span><span class="hl kwb">$a</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}} }</span></li>
<li id="n_302" class="hl">                          <span class="hl kwc">grep </span><span class="hl opt">{ </span><span class="hl kwc">exists </span><span class="hl kwb">$_</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">} &amp;&amp; </span><span class="hl kwb">$_</span><span class="hl opt">-&gt;{</span>feed<span class="hl opt">} </span><span class="hl kwc">eq </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">} &amp;&amp; </span><span class="hl kwb">$IkiWiki</span><span class="hl opt">::</span>pagectime<span class="hl opt">{</span><span class="hl kwb">$_</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}} }</span></li>
<li id="n_303" class="hl">                          <span class="hl kwc">values </span><span class="hl kwb">%guids</span><span class="hl opt">) {</span></li>
<li id="n_304" class="hl">            <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expireage<span class="hl opt">}) {</span></li>
<li id="n_305" class="hl">                <span class="hl kwc">my </span><span class="hl kwb">$days_old </span><span class="hl opt">= (</span><span class="hl kwc">time </span><span class="hl opt">- </span><span class="hl kwb">$IkiWiki</span><span class="hl opt">::</span>pagectime<span class="hl opt">{</span><span class="hl kwb">$item</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}}) </span><span class="hl kwd">/ 60 / </span><span class="hl num">60 </span><span class="hl opt">/ </span><span class="hl num">24</span><span class="hl opt">;</span></li>
<li id="n_306" class="hl">                <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$days_old </span><span class="hl opt">&gt; </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expireage<span class="hl opt">}) {</span></li>
<li id="n_307" class="hl">                    debug<span class="hl opt">(</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;expiring </span><span class="hl ipl">%s </span><span class="hl sng">(</span><span class="hl ipl">%s </span><span class="hl sng">days old)&quot;</span><span class="hl opt">),</span></li>
<li id="n_308" class="hl">                        <span class="hl kwb">$item</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}, </span><span class="hl kwc">int</span><span class="hl opt">(</span><span class="hl kwb">$days_old</span><span class="hl opt">)));</span></li>
<li id="n_309" class="hl">                    <span class="hl kwb">$item</span><span class="hl opt">-&gt;{</span>expired<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_310" class="hl">                <span class="hl opt">}</span></li>
<li id="n_311" class="hl">            <span class="hl opt">}</span></li>
<li id="n_312" class="hl">            <span class="hl kwa">elsif </span><span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expirecount<span class="hl opt">} &amp;&amp;</span></li>
<li id="n_313" class="hl">                   <span class="hl kwb">$count </span><span class="hl opt">&gt;= </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>expirecount<span class="hl opt">}) {</span></li>
<li id="n_314" class="hl">                debug<span class="hl opt">(</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;expiring </span><span class="hl ipl">%s</span><span class="hl sng">&quot;</span><span class="hl opt">), </span><span class="hl kwb">$item</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}));</span></li>
<li id="n_315" class="hl">                <span class="hl kwb">$item</span><span class="hl opt">-&gt;{</span>expired<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_316" class="hl">            <span class="hl opt">}</span></li>
<li id="n_317" class="hl">            <span class="hl kwa">else </span><span class="hl opt">{</span></li>
<li id="n_318" class="hl">                <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwb">$seen</span><span class="hl opt">{</span><span class="hl kwb">$item</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}}) {</span></li>
<li id="n_319" class="hl">                    <span class="hl kwb">$seen</span><span class="hl opt">{</span><span class="hl kwb">$item</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_320" class="hl">                    <span class="hl kwb">$count++</span><span class="hl opt">;</span></li>
<li id="n_321" class="hl">                <span class="hl opt">}</span></li>
<li id="n_322" class="hl">            <span class="hl opt">}</span></li>
<li id="n_323" class="hl">        <span class="hl opt">}</span></li>
<li id="n_324" class="hl">    <span class="hl opt">}</span></li>
<li id="n_325" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_326" class="hl"></li>
<li id="n_327" class="hl"><span class="hl kwa">sub </span>needsaggregate <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_328" class="hl">    <span class="hl kwa">return </span><span class="hl kwc">values </span><span class="hl kwb">%feeds </span><span class="hl kwa">if </span><span class="hl kwb">$config</span><span class="hl opt">{</span>rebuild<span class="hl opt">};</span></li>
<li id="n_329" class="hl">    <span class="hl kwa">return </span><span class="hl kwc">grep </span><span class="hl opt">{ </span><span class="hl kwc">time </span><span class="hl opt">- </span><span class="hl kwb">$_</span><span class="hl opt">-&gt;{</span>lastupdate<span class="hl opt">} &gt;= </span><span class="hl kwb">$_</span><span class="hl opt">-&gt;{</span>updateinterval<span class="hl opt">} } </span><span class="hl kwc">values </span><span class="hl kwb">%feeds</span><span class="hl opt">;</span></li>
<li id="n_330" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_331" class="hl"></li>
<li id="n_332" class="hl"><span class="hl kwa">sub </span>aggregate <span class="hl opt">(&#64;) { </span><span class="hl slc">#{{{</span></li>
<li id="n_333" class="hl">    <span class="hl kwc">eval </span><span class="hl sng">q{use XML::Feed}</span><span class="hl opt">;</span></li>
<li id="n_334" class="hl">    error<span class="hl opt">(</span><span class="hl kwb">$&#64;</span><span class="hl opt">) </span><span class="hl kwa">if </span><span class="hl kwb">$&#64;</span><span class="hl opt">;</span></li>
<li id="n_335" class="hl">    <span class="hl kwc">eval </span><span class="hl sng">q{use URI::Fetch}</span><span class="hl opt">;</span></li>
<li id="n_336" class="hl">    error<span class="hl opt">(</span><span class="hl kwb">$&#64;</span><span class="hl opt">) </span><span class="hl kwa">if </span><span class="hl kwb">$&#64;</span><span class="hl opt">;</span></li>
<li id="n_337" class="hl"></li>
<li id="n_338" class="hl">    <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$feed </span><span class="hl opt">(</span><span class="hl kwb">&#64;_</span><span class="hl opt">) {</span></li>
<li id="n_339" class="hl">        <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>lastupdate<span class="hl opt">}=</span><span class="hl kwc">time</span><span class="hl opt">;</span></li>
<li id="n_340" class="hl">        <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>newposts<span class="hl opt">}=</span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_341" class="hl">        <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}=</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;processed ok at </span><span class="hl ipl">%s</span><span class="hl sng">&quot;</span><span class="hl opt">),</span></li>
<li id="n_342" class="hl">            displaytime<span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>lastupdate<span class="hl opt">}));</span></li>
<li id="n_343" class="hl">        <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">}=</span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_344" class="hl"></li>
<li id="n_345" class="hl">        debug<span class="hl opt">(</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;checking feed </span><span class="hl ipl">%s </span><span class="hl sng">...&quot;</span><span class="hl opt">), </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">}));</span></li>
<li id="n_346" class="hl"></li>
<li id="n_347" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwc">length </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>feedurl<span class="hl opt">}) {</span></li>
<li id="n_348" class="hl">            <span class="hl kwc">my </span><span class="hl kwb">&#64;urls</span><span class="hl opt">=</span>XML<span class="hl opt">::</span>Feed-<span class="hl opt">&gt;</span><span class="hl kwd">find_feeds</span><span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>url<span class="hl opt">});</span></li>
<li id="n_349" class="hl">            <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwb">&#64;urls</span><span class="hl opt">) {</span></li>
<li id="n_350" class="hl">                <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}=</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;could not find feed at </span><span class="hl ipl">%s</span><span class="hl sng">&quot;</span><span class="hl opt">), </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>url<span class="hl opt">});</span></li>
<li id="n_351" class="hl">                <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_352" class="hl">                debug<span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">});</span></li>
<li id="n_353" class="hl">                <span class="hl kwa">next</span><span class="hl opt">;</span></li>
<li id="n_354" class="hl">            <span class="hl opt">}</span></li>
<li id="n_355" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>feedurl<span class="hl opt">}=</span><span class="hl kwc">pop </span><span class="hl kwb">&#64;urls</span><span class="hl opt">;</span></li>
<li id="n_356" class="hl">        <span class="hl opt">}</span></li>
<li id="n_357" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$res</span><span class="hl opt">=</span>URI<span class="hl opt">::</span>Fetch-<span class="hl opt">&gt;</span><span class="hl kwd">fetch</span><span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>feedurl<span class="hl opt">});</span></li>
<li id="n_358" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwb">$res</span><span class="hl opt">) {</span></li>
<li id="n_359" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}=</span>URI<span class="hl opt">::</span>Fetch-<span class="hl opt">&gt;</span><span class="hl kwd">errstr</span><span class="hl opt">;</span></li>
<li id="n_360" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_361" class="hl">            debug<span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">});</span></li>
<li id="n_362" class="hl">            <span class="hl kwa">next</span><span class="hl opt">;</span></li>
<li id="n_363" class="hl">        <span class="hl opt">}</span></li>
<li id="n_364" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$res</span><span class="hl opt">-&gt;</span><span class="hl kwd">status </span><span class="hl opt">== </span>URI<span class="hl opt">::</span>Fetch<span class="hl opt">::</span>URI_GONE<span class="hl opt">()) {</span></li>
<li id="n_365" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}=</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;feed not found&quot;</span><span class="hl opt">);</span></li>
<li id="n_366" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_367" class="hl">            debug<span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">});</span></li>
<li id="n_368" class="hl">            <span class="hl kwa">next</span><span class="hl opt">;</span></li>
<li id="n_369" class="hl">        <span class="hl opt">}</span></li>
<li id="n_370" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$content</span><span class="hl opt">=</span><span class="hl kwb">$res</span><span class="hl opt">-&gt;</span><span class="hl kwd">content</span><span class="hl opt">;</span></li>
<li id="n_371" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$f</span><span class="hl opt">=</span><span class="hl kwc">eval</span><span class="hl opt">{</span>XML<span class="hl opt">::</span>Feed-<span class="hl opt">&gt;</span><span class="hl kwd">parse</span><span class="hl opt">(</span>\<span class="hl kwb">$content</span><span class="hl opt">)};</span></li>
<li id="n_372" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$&#64;</span><span class="hl opt">) {</span></li>
<li id="n_373" class="hl">            <span class="hl slc"># One common cause of XML::Feed crashing is a feed</span></li>
<li id="n_374" class="hl">            <span class="hl slc"># that contains invalid UTF-8 sequences. Convert</span></li>
<li id="n_375" class="hl">            <span class="hl slc"># feed to ascii to try to work around.</span></li>
<li id="n_376" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}.=</span><span class="hl sng">&quot; &quot;</span><span class="hl opt">.</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;(invalid UTF-8 stripped from feed)&quot;</span><span class="hl opt">));</span></li>
<li id="n_377" class="hl">            <span class="hl kwb">$content</span><span class="hl opt">=</span>Encode<span class="hl opt">::</span>decode_utf8<span class="hl opt">(</span><span class="hl kwb">$content</span><span class="hl opt">);</span></li>
<li id="n_378" class="hl">            <span class="hl kwb">$f</span><span class="hl opt">=</span><span class="hl kwc">eval</span><span class="hl opt">{</span>XML<span class="hl opt">::</span>Feed-<span class="hl opt">&gt;</span><span class="hl kwd">parse</span><span class="hl opt">(</span>\<span class="hl kwb">$content</span><span class="hl opt">)};</span></li>
<li id="n_379" class="hl">        <span class="hl opt">}</span></li>
<li id="n_380" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$&#64;</span><span class="hl opt">) {</span></li>
<li id="n_381" class="hl">            <span class="hl slc"># Another possibility is badly escaped entities.</span></li>
<li id="n_382" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}.=</span><span class="hl sng">&quot; &quot;</span><span class="hl opt">.</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;(feed entities escaped)&quot;</span><span class="hl opt">));</span></li>
<li id="n_383" class="hl">            <span class="hl kwb">$content</span><span class="hl opt">=~</span><span class="hl kwd">s/\&amp;(?!amp)(\w+);/&amp;amp;$1;/g</span><span class="hl opt">;</span></li>
<li id="n_384" class="hl">            <span class="hl kwb">$content</span><span class="hl opt">=</span>Encode<span class="hl opt">::</span>decode_utf8<span class="hl opt">(</span><span class="hl kwb">$content</span><span class="hl opt">);</span></li>
<li id="n_385" class="hl">            <span class="hl kwb">$f</span><span class="hl opt">=</span><span class="hl kwc">eval</span><span class="hl opt">{</span>XML<span class="hl opt">::</span>Feed-<span class="hl opt">&gt;</span><span class="hl kwd">parse</span><span class="hl opt">(</span>\<span class="hl kwb">$content</span><span class="hl opt">)};</span></li>
<li id="n_386" class="hl">        <span class="hl opt">}</span></li>
<li id="n_387" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwb">$&#64;</span><span class="hl opt">) {</span></li>
<li id="n_388" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}=</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;feed crashed XML::Feed!&quot;</span><span class="hl opt">).</span><span class="hl sng">&quot; (</span><span class="hl ipl">$&#64;</span><span class="hl sng">)&quot;</span><span class="hl opt">;</span></li>
<li id="n_389" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_390" class="hl">            debug<span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">});</span></li>
<li id="n_391" class="hl">            <span class="hl kwa">next</span><span class="hl opt">;</span></li>
<li id="n_392" class="hl">        <span class="hl opt">}</span></li>
<li id="n_393" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwb">$f</span><span class="hl opt">) {</span></li>
<li id="n_394" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">}=</span>XML<span class="hl opt">::</span>Feed-<span class="hl opt">&gt;</span><span class="hl kwd">errstr</span><span class="hl opt">;</span></li>
<li id="n_395" class="hl">            <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>error<span class="hl opt">}=</span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_396" class="hl">            debug<span class="hl opt">(</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>message<span class="hl opt">});</span></li>
<li id="n_397" class="hl">            <span class="hl kwa">next</span><span class="hl opt">;</span></li>
<li id="n_398" class="hl">        <span class="hl opt">}</span></li>
<li id="n_399" class="hl"></li>
<li id="n_400" class="hl">        <span class="hl kwa">foreach </span><span class="hl kwc">my </span><span class="hl kwb">$entry </span><span class="hl opt">(</span><span class="hl kwb">$f</span><span class="hl opt">-&gt;</span><span class="hl kwd">entries</span><span class="hl opt">) {</span></li>
<li id="n_401" class="hl">            add_page<span class="hl opt">(</span></li>
<li id="n_402" class="hl">                feed <span class="hl opt">=&gt; </span><span class="hl kwb">$feed</span><span class="hl opt">,</span></li>
<li id="n_403" class="hl">                copyright <span class="hl opt">=&gt; </span><span class="hl kwb">$f</span><span class="hl opt">-&gt;</span><span class="hl kwd">copyright</span><span class="hl opt">,</span></li>
<li id="n_404" class="hl">                title <span class="hl opt">=&gt; </span><span class="hl kwc">defined </span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">title </span><span class="hl opt">? </span>decode_entities<span class="hl opt">(</span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">title</span><span class="hl opt">) : </span><span class="hl sng">&quot;untitled&quot;</span><span class="hl opt">,</span></li>
<li id="n_405" class="hl">                <span class="hl kwc">link </span><span class="hl opt">=&gt; </span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwc">link</span><span class="hl opt">,</span></li>
<li id="n_406" class="hl">                content <span class="hl opt">=&gt; </span><span class="hl kwc">defined </span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">content</span><span class="hl opt">-&gt;</span><span class="hl kwd">body </span><span class="hl opt">? </span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">content</span><span class="hl opt">-&gt;</span><span class="hl kwd">body </span><span class="hl opt">: </span><span class="hl sng">&quot;&quot;</span><span class="hl opt">,</span></li>
<li id="n_407" class="hl">                guid <span class="hl opt">=&gt; </span><span class="hl kwc">defined </span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">id </span><span class="hl opt">? </span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">id </span><span class="hl opt">: </span><span class="hl kwc">time</span><span class="hl opt">.</span><span class="hl sng">&quot;_&quot;</span><span class="hl opt">.</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;</span><span class="hl kwd">name</span><span class="hl opt">,</span></li>
<li id="n_408" class="hl">                ctime <span class="hl opt">=&gt; </span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">issued </span><span class="hl opt">? (</span><span class="hl kwb">$entry</span><span class="hl opt">-&gt;</span><span class="hl kwd">issued</span><span class="hl opt">-&gt;</span><span class="hl kwd">epoch </span><span class="hl opt">|| </span><span class="hl kwc">time</span><span class="hl opt">) : </span><span class="hl kwc">time</span><span class="hl opt">,</span></li>
<li id="n_409" class="hl">            <span class="hl opt">);</span></li>
<li id="n_410" class="hl">        <span class="hl opt">}</span></li>
<li id="n_411" class="hl">    <span class="hl opt">}</span></li>
<li id="n_412" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_413" class="hl"></li>
<li id="n_414" class="hl"><span class="hl kwa">sub </span>add_page <span class="hl opt">(&#64;) { </span><span class="hl slc">#{{{</span></li>
<li id="n_415" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">%params</span><span class="hl opt">=</span><span class="hl kwb">&#64;_</span><span class="hl opt">;</span></li>
<li id="n_416" class="hl">    </li>
<li id="n_417" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$feed</span><span class="hl opt">=</span><span class="hl kwb">$params</span><span class="hl opt">{</span>feed<span class="hl opt">};</span></li>
<li id="n_418" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$guid</span><span class="hl opt">={};</span></li>
<li id="n_419" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$mtime</span><span class="hl opt">;</span></li>
<li id="n_420" class="hl">    <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$guids</span><span class="hl opt">{</span><span class="hl kwb">$params</span><span class="hl opt">{</span>guid<span class="hl opt">}}) {</span></li>
<li id="n_421" class="hl">        <span class="hl slc"># updating an existing post</span></li>
<li id="n_422" class="hl">        <span class="hl kwb">$guid</span><span class="hl opt">=</span><span class="hl kwb">$guids</span><span class="hl opt">{</span><span class="hl kwb">$params</span><span class="hl opt">{</span>guid<span class="hl opt">}};</span></li>
<li id="n_423" class="hl">        <span class="hl kwa">return if </span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>expired<span class="hl opt">};</span></li>
<li id="n_424" class="hl">    <span class="hl opt">}</span></li>
<li id="n_425" class="hl">    <span class="hl kwa">else </span><span class="hl opt">{</span></li>
<li id="n_426" class="hl">        <span class="hl slc"># new post</span></li>
<li id="n_427" class="hl">        <span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>guid<span class="hl opt">}=</span><span class="hl kwb">$params</span><span class="hl opt">{</span>guid<span class="hl opt">};</span></li>
<li id="n_428" class="hl">        <span class="hl kwb">$guids</span><span class="hl opt">{</span><span class="hl kwb">$params</span><span class="hl opt">{</span>guid<span class="hl opt">}}=</span><span class="hl kwb">$guid</span><span class="hl opt">;</span></li>
<li id="n_429" class="hl">        <span class="hl kwb">$mtime</span><span class="hl opt">=</span><span class="hl kwb">$params</span><span class="hl opt">{</span>ctime<span class="hl opt">};</span></li>
<li id="n_430" class="hl">        <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>numposts<span class="hl opt">}++;</span></li>
<li id="n_431" class="hl">        <span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>newposts<span class="hl opt">}++;</span></li>
<li id="n_432" class="hl"></li>
<li id="n_433" class="hl">        <span class="hl slc"># assign it an unused page</span></li>
<li id="n_434" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$page</span><span class="hl opt">=</span>IkiWiki<span class="hl opt">::</span>titlepage<span class="hl opt">(</span><span class="hl kwb">$params</span><span class="hl opt">{</span>title<span class="hl opt">});</span></li>
<li id="n_435" class="hl">        <span class="hl slc"># escape slashes and periods in title so it doesn&#39;t specify</span></li>
<li id="n_436" class="hl">        <span class="hl slc"># directory name or trigger &quot;..&quot; disallowing code.</span></li>
<li id="n_437" class="hl">        <span class="hl kwb">$page</span><span class="hl opt">=~</span><span class="hl kwd">s!([/.])!&quot;__&quot;.ord($1).&quot;__&quot;!eg</span><span class="hl opt">;</span></li>
<li id="n_438" class="hl">        <span class="hl kwb">$page</span><span class="hl opt">=</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>dir<span class="hl opt">}.</span><span class="hl sng">&quot;/&quot;</span><span class="hl opt">.</span><span class="hl kwb">$page</span><span class="hl opt">;</span></li>
<li id="n_439" class="hl">        <span class="hl opt">(</span><span class="hl kwb">$page</span><span class="hl opt">)=</span><span class="hl kwb">$page</span><span class="hl opt">=~</span><span class="hl kwd">/$config{wiki_file_regexp}/</span><span class="hl opt">;</span></li>
<li id="n_440" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwc">defined </span><span class="hl kwb">$page </span><span class="hl opt">|| ! </span><span class="hl kwc">length </span><span class="hl kwb">$page</span><span class="hl opt">) {</span></li>
<li id="n_441" class="hl">            <span class="hl kwb">$page</span><span class="hl opt">=</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>dir<span class="hl opt">}.</span><span class="hl sng">&quot;/item&quot;</span><span class="hl opt">;</span></li>
<li id="n_442" class="hl">        <span class="hl opt">}</span></li>
<li id="n_443" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$c</span><span class="hl opt">=</span><span class="hl sng">&quot;&quot;</span><span class="hl opt">;</span></li>
<li id="n_444" class="hl">        <span class="hl kwa">while </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$IkiWiki</span><span class="hl opt">::</span>pagecase<span class="hl opt">{</span><span class="hl kwc">lc </span><span class="hl kwb">$page</span><span class="hl opt">.</span><span class="hl kwb">$c</span><span class="hl opt">} ||</span></li>
<li id="n_445" class="hl">               <span class="hl opt">-</span>e pagefile<span class="hl opt">(</span><span class="hl kwb">$page</span><span class="hl opt">.</span><span class="hl kwb">$c</span><span class="hl opt">)) {</span></li>
<li id="n_446" class="hl">            <span class="hl kwb">$c++</span></li>
<li id="n_447" class="hl">        <span class="hl opt">}</span></li>
<li id="n_448" class="hl"></li>
<li id="n_449" class="hl">        <span class="hl slc"># Make sure that the file name isn&#39;t too long. </span></li>
<li id="n_450" class="hl">        <span class="hl slc"># NB: This doesn&#39;t check for path length limits.</span></li>
<li id="n_451" class="hl">        <span class="hl kwc">my </span><span class="hl kwb">$max</span><span class="hl opt">=</span>POSIX<span class="hl opt">::</span>pathconf<span class="hl opt">(</span><span class="hl kwb">$config</span><span class="hl opt">{</span>srcdir<span class="hl opt">}, &amp;</span>POSIX<span class="hl opt">::</span>_PC_NAME_MAX<span class="hl opt">);</span></li>
<li id="n_452" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">defined </span><span class="hl kwb">$max </span><span class="hl opt">&amp;&amp; </span><span class="hl kwc">length</span><span class="hl opt">(</span>htmlfn<span class="hl opt">(</span><span class="hl kwb">$page</span><span class="hl opt">)) &gt;= </span><span class="hl kwb">$max</span><span class="hl opt">) {</span></li>
<li id="n_453" class="hl">            <span class="hl kwb">$c</span><span class="hl opt">=</span><span class="hl sng">&quot;&quot;</span><span class="hl opt">;</span></li>
<li id="n_454" class="hl">            <span class="hl kwb">$page</span><span class="hl opt">=</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>dir<span class="hl opt">}.</span><span class="hl sng">&quot;/item&quot;</span><span class="hl opt">;</span></li>
<li id="n_455" class="hl">            <span class="hl kwa">while </span><span class="hl opt">(</span><span class="hl kwc">exists </span><span class="hl kwb">$IkiWiki</span><span class="hl opt">::</span>pagecase<span class="hl opt">{</span><span class="hl kwc">lc </span><span class="hl kwb">$page</span><span class="hl opt">.</span><span class="hl kwb">$c</span><span class="hl opt">} ||</span></li>
<li id="n_456" class="hl">                   <span class="hl opt">-</span>e pagefile<span class="hl opt">(</span><span class="hl kwb">$page</span><span class="hl opt">.</span><span class="hl kwb">$c</span><span class="hl opt">)) {</span></li>
<li id="n_457" class="hl">                <span class="hl kwb">$c++</span></li>
<li id="n_458" class="hl">            <span class="hl opt">}</span></li>
<li id="n_459" class="hl">        <span class="hl opt">}</span></li>
<li id="n_460" class="hl"></li>
<li id="n_461" class="hl">        <span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}=</span><span class="hl kwb">$page</span><span class="hl opt">;</span></li>
<li id="n_462" class="hl">        debug<span class="hl opt">(</span><span class="hl kwc">sprintf</span><span class="hl opt">(</span>gettext<span class="hl opt">(</span><span class="hl sng">&quot;creating new page </span><span class="hl ipl">%s</span><span class="hl sng">&quot;</span><span class="hl opt">), </span><span class="hl kwb">$page</span><span class="hl opt">));</span></li>
<li id="n_463" class="hl">    <span class="hl opt">}</span></li>
<li id="n_464" class="hl">    <span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>feed<span class="hl opt">}=</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">};</span></li>
<li id="n_465" class="hl">    </li>
<li id="n_466" class="hl">    <span class="hl slc"># To write or not to write? Need to avoid writing unchanged pages</span></li>
<li id="n_467" class="hl">    <span class="hl slc"># to avoid unneccessary rebuilding. The mtime from rss cannot be</span></li>
<li id="n_468" class="hl">    <span class="hl slc"># trusted; let&#39;s use a digest.</span></li>
<li id="n_469" class="hl">    <span class="hl kwc">eval </span><span class="hl sng">q{use Digest::MD5 &#39;md5_hex&#39;}</span><span class="hl opt">;</span></li>
<li id="n_470" class="hl">    error<span class="hl opt">(</span><span class="hl kwb">$&#64;</span><span class="hl opt">) </span><span class="hl kwa">if </span><span class="hl kwb">$&#64;</span><span class="hl opt">;</span></li>
<li id="n_471" class="hl">    <span class="hl kwa">require </span>Encode<span class="hl opt">;</span></li>
<li id="n_472" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$digest</span><span class="hl opt">=</span>md5_hex<span class="hl opt">(</span>Encode<span class="hl opt">::</span>encode_utf8<span class="hl opt">(</span><span class="hl kwb">$params</span><span class="hl opt">{</span>content<span class="hl opt">}));</span></li>
<li id="n_473" class="hl">    <span class="hl kwa">return unless </span><span class="hl opt">! </span><span class="hl kwc">exists </span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>md5<span class="hl opt">} || </span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>md5<span class="hl opt">} </span><span class="hl kwc">ne </span><span class="hl kwb">$digest </span><span class="hl opt">|| </span><span class="hl kwb">$config</span><span class="hl opt">{</span>rebuild<span class="hl opt">};</span></li>
<li id="n_474" class="hl">    <span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>md5<span class="hl opt">}=</span><span class="hl kwb">$digest</span><span class="hl opt">;</span></li>
<li id="n_475" class="hl"></li>
<li id="n_476" class="hl">    <span class="hl slc"># Create the page.</span></li>
<li id="n_477" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$template</span><span class="hl opt">=</span>template<span class="hl opt">(</span><span class="hl sng">&quot;aggregatepost.tmpl&quot;</span><span class="hl opt">, </span>blind_cache <span class="hl opt">=&gt; </span><span class="hl num">1</span><span class="hl opt">);</span></li>
<li id="n_478" class="hl">    <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">param</span><span class="hl opt">(</span>title <span class="hl opt">=&gt; </span><span class="hl kwb">$params</span><span class="hl opt">{</span>title<span class="hl opt">})</span></li>
<li id="n_479" class="hl">        <span class="hl kwa">if </span><span class="hl kwc">defined </span><span class="hl kwb">$params</span><span class="hl opt">{</span>title<span class="hl opt">} &amp;&amp; </span><span class="hl kwc">length</span><span class="hl opt">(</span><span class="hl kwb">$params</span><span class="hl opt">{</span>title<span class="hl opt">});</span></li>
<li id="n_480" class="hl">    <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">param</span><span class="hl opt">(</span>content <span class="hl opt">=&gt; </span>htmlescape<span class="hl opt">(</span>htmlabs<span class="hl opt">(</span><span class="hl kwb">$params</span><span class="hl opt">{</span>content<span class="hl opt">}, </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>feedurl<span class="hl opt">})));</span></li>
<li id="n_481" class="hl">    <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">param</span><span class="hl opt">(</span>name <span class="hl opt">=&gt; </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>name<span class="hl opt">});</span></li>
<li id="n_482" class="hl">    <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">param</span><span class="hl opt">(</span>url <span class="hl opt">=&gt; </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>url<span class="hl opt">});</span></li>
<li id="n_483" class="hl">    <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">param</span><span class="hl opt">(</span>copyright <span class="hl opt">=&gt; </span><span class="hl kwb">$params</span><span class="hl opt">{</span>copyright<span class="hl opt">})</span></li>
<li id="n_484" class="hl">        <span class="hl kwa">if </span><span class="hl kwc">defined </span><span class="hl kwb">$params</span><span class="hl opt">{</span>copyright<span class="hl opt">} &amp;&amp; </span><span class="hl kwc">length </span><span class="hl kwb">$params</span><span class="hl opt">{</span>copyright<span class="hl opt">};</span></li>
<li id="n_485" class="hl">    <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">param</span><span class="hl opt">(</span>permalink <span class="hl opt">=&gt; </span>urlabs<span class="hl opt">(</span><span class="hl kwb">$params</span><span class="hl opt">{</span><span class="hl kwc">link</span><span class="hl opt">}, </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>feedurl<span class="hl opt">}))</span></li>
<li id="n_486" class="hl">        <span class="hl kwa">if </span><span class="hl kwc">defined </span><span class="hl kwb">$params</span><span class="hl opt">{</span><span class="hl kwc">link</span><span class="hl opt">};</span></li>
<li id="n_487" class="hl">    <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">ref </span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>tags<span class="hl opt">}) {</span></li>
<li id="n_488" class="hl">        <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">param</span><span class="hl opt">(</span>tags <span class="hl opt">=&gt; [</span><span class="hl kwc">map </span><span class="hl opt">{ </span>tag <span class="hl opt">=&gt; </span><span class="hl kwb">$_ </span><span class="hl opt">}, &#64;{</span><span class="hl kwb">$feed</span><span class="hl opt">-&gt;{</span>tags<span class="hl opt">}}]);</span></li>
<li id="n_489" class="hl">    <span class="hl opt">}</span></li>
<li id="n_490" class="hl">    writefile<span class="hl opt">(</span>htmlfn<span class="hl opt">(</span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">}), </span><span class="hl kwb">$config</span><span class="hl opt">{</span>srcdir<span class="hl opt">},</span></li>
<li id="n_491" class="hl">        <span class="hl kwb">$template</span><span class="hl opt">-&gt;</span><span class="hl kwd">output</span><span class="hl opt">);</span></li>
<li id="n_492" class="hl"></li>
<li id="n_493" class="hl">    <span class="hl slc"># Set the mtime, this lets the build process get the right creation</span></li>
<li id="n_494" class="hl">    <span class="hl slc"># time on record for the new page.</span></li>
<li id="n_495" class="hl">    <span class="hl kwc">utime </span><span class="hl kwb">$mtime</span><span class="hl opt">, </span><span class="hl kwb">$mtime</span><span class="hl opt">, </span>pagefile<span class="hl opt">(</span><span class="hl kwb">$guid</span><span class="hl opt">-&gt;{</span>page<span class="hl opt">})</span></li>
<li id="n_496" class="hl">        <span class="hl kwa">if </span><span class="hl kwc">defined </span><span class="hl kwb">$mtime </span><span class="hl opt">&amp;&amp; </span><span class="hl kwb">$mtime </span><span class="hl opt">&lt;= </span><span class="hl kwc">time</span><span class="hl opt">;</span></li>
<li id="n_497" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_498" class="hl"></li>
<li id="n_499" class="hl"><span class="hl kwa">sub </span>htmlescape <span class="hl opt">($) { </span><span class="hl slc">#{{{</span></li>
<li id="n_500" class="hl">    <span class="hl slc"># escape accidental wikilinks and preprocessor stuff</span></li>
<li id="n_501" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$html</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_502" class="hl">    <span class="hl kwb">$html</span><span class="hl opt">=~</span><span class="hl kwd">s/(?&lt;!\\)\[\[/\\\[\[/g</span><span class="hl opt">;</span></li>
<li id="n_503" class="hl">    <span class="hl kwa">return </span><span class="hl kwb">$html</span><span class="hl opt">;</span></li>
<li id="n_504" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_505" class="hl"></li>
<li id="n_506" class="hl"><span class="hl kwa">sub </span>urlabs <span class="hl opt">(</span><span class="hl kwb">$$</span><span class="hl opt">) { </span><span class="hl slc">#{{{</span></li>
<li id="n_507" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$url</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_508" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$urlbase</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_509" class="hl"></li>
<li id="n_510" class="hl">    URI-<span class="hl opt">&gt;</span><span class="hl kwd">new_abs</span><span class="hl opt">(</span><span class="hl kwb">$url</span><span class="hl opt">, </span><span class="hl kwb">$urlbase</span><span class="hl opt">)-&gt;</span><span class="hl kwd">as_string</span><span class="hl opt">;</span></li>
<li id="n_511" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_512" class="hl"></li>
<li id="n_513" class="hl"><span class="hl kwa">sub </span>htmlabs <span class="hl opt">(</span><span class="hl kwb">$$</span><span class="hl opt">) { </span><span class="hl slc">#{{{</span></li>
<li id="n_514" class="hl">    <span class="hl slc"># Convert links in html from relative to absolute.</span></li>
<li id="n_515" class="hl">    <span class="hl slc"># Note that this is a heuristic, which is not specified by the rss</span></li>
<li id="n_516" class="hl">    <span class="hl slc"># spec and may not be right for all feeds. Also, see Debian</span></li>
<li id="n_517" class="hl">    <span class="hl slc"># bug #381359.</span></li>
<li id="n_518" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$html</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_519" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$urlbase</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_520" class="hl"></li>
<li id="n_521" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$ret</span><span class="hl opt">=</span><span class="hl sng">&quot;&quot;</span><span class="hl opt">;</span></li>
<li id="n_522" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$p </span><span class="hl opt">= </span>HTML<span class="hl opt">::</span>Parser-<span class="hl opt">&gt;</span><span class="hl kwd">new</span><span class="hl opt">(</span>api_version <span class="hl opt">=&gt; </span><span class="hl num">3</span><span class="hl opt">);</span></li>
<li id="n_523" class="hl">    <span class="hl kwb">$p</span><span class="hl opt">-&gt;</span><span class="hl kwd">handler</span><span class="hl opt">(</span><span class="hl kwa">default </span><span class="hl opt">=&gt; </span><span class="hl kwa">sub </span><span class="hl opt">{ </span><span class="hl kwb">$ret</span><span class="hl opt">.=</span><span class="hl kwc">join</span><span class="hl opt">(</span><span class="hl sng">&quot;&quot;</span><span class="hl opt">, </span><span class="hl kwb">&#64;_</span><span class="hl opt">) }, </span><span class="hl sng">&quot;text&quot;</span><span class="hl opt">);</span></li>
<li id="n_524" class="hl">    <span class="hl kwb">$p</span><span class="hl opt">-&gt;</span><span class="hl kwd">handler</span><span class="hl opt">(</span>start <span class="hl opt">=&gt; </span><span class="hl kwa">sub </span><span class="hl opt">{</span></li>
<li id="n_525" class="hl">        <span class="hl kwc">my </span><span class="hl opt">(</span><span class="hl kwb">$tagname</span><span class="hl opt">, </span><span class="hl kwb">$pos</span><span class="hl opt">, </span><span class="hl kwb">$text</span><span class="hl opt">) = </span><span class="hl kwb">&#64;_</span><span class="hl opt">;</span></li>
<li id="n_526" class="hl">        <span class="hl kwa">if </span><span class="hl opt">(</span><span class="hl kwc">ref </span><span class="hl kwb">$HTML</span><span class="hl opt">::</span>Tagset<span class="hl opt">::</span>linkElements<span class="hl opt">{</span><span class="hl kwb">$tagname</span><span class="hl opt">}) {</span></li>
<li id="n_527" class="hl">            <span class="hl kwa">while </span><span class="hl opt">(</span><span class="hl num">4 </span><span class="hl opt">&lt;= </span><span class="hl kwb">&#64;$pos</span><span class="hl opt">) {</span></li>
<li id="n_528" class="hl">                <span class="hl slc"># use attribute sets from right to left</span></li>
<li id="n_529" class="hl">                <span class="hl slc"># to avoid invalidating the offsets</span></li>
<li id="n_530" class="hl">                <span class="hl slc"># when replacing the values</span></li>
<li id="n_531" class="hl">                <span class="hl kwc">my</span><span class="hl opt">(</span><span class="hl kwb">$k_offset</span><span class="hl opt">, </span><span class="hl kwb">$k_len</span><span class="hl opt">, </span><span class="hl kwb">$v_offset</span><span class="hl opt">, </span><span class="hl kwb">$v_len</span><span class="hl opt">) =</span></li>
<li id="n_532" class="hl">                    <span class="hl kwc">splice</span><span class="hl opt">(</span><span class="hl kwb">&#64;$pos</span><span class="hl opt">, -</span><span class="hl num">4</span><span class="hl opt">);</span></li>
<li id="n_533" class="hl">                <span class="hl kwc">my </span><span class="hl kwb">$attrname </span><span class="hl opt">= </span><span class="hl kwc">lc</span><span class="hl opt">(</span><span class="hl kwc">substr</span><span class="hl opt">(</span><span class="hl kwb">$text</span><span class="hl opt">, </span><span class="hl kwb">$k_offset</span><span class="hl opt">, </span><span class="hl kwb">$k_len</span><span class="hl opt">));</span></li>
<li id="n_534" class="hl">                <span class="hl kwa">next unless </span><span class="hl kwc">grep </span><span class="hl opt">{ </span><span class="hl kwb">$_ </span><span class="hl kwc">eq </span><span class="hl kwb">$attrname </span><span class="hl opt">} &#64;{</span><span class="hl kwb">$HTML</span><span class="hl opt">::</span>Tagset<span class="hl opt">::</span>linkElements<span class="hl opt">{</span><span class="hl kwb">$tagname</span><span class="hl opt">}};</span></li>
<li id="n_535" class="hl">                <span class="hl kwa">next unless </span><span class="hl kwb">$v_offset</span><span class="hl opt">; </span><span class="hl slc"># 0 v_offset means no value</span></li>
<li id="n_536" class="hl">                <span class="hl kwc">my </span><span class="hl kwb">$v </span><span class="hl opt">= </span><span class="hl kwc">substr</span><span class="hl opt">(</span><span class="hl kwb">$text</span><span class="hl opt">, </span><span class="hl kwb">$v_offset</span><span class="hl opt">, </span><span class="hl kwb">$v_len</span><span class="hl opt">);</span></li>
<li id="n_537" class="hl">                <span class="hl kwb">$v </span><span class="hl opt">=~ </span><span class="hl kwd">s/^([\&#39;\&quot;])(.*)\1$/$2/</span><span class="hl opt">;</span></li>
<li id="n_538" class="hl">                <span class="hl kwc">my </span><span class="hl kwb">$new_v</span><span class="hl opt">=</span>urlabs<span class="hl opt">(</span><span class="hl kwb">$v</span><span class="hl opt">, </span><span class="hl kwb">$urlbase</span><span class="hl opt">);</span></li>
<li id="n_539" class="hl">                <span class="hl kwb">$new_v </span><span class="hl opt">=~ </span><span class="hl kwd">s/\&quot;/&amp;quot;/g</span><span class="hl opt">; </span><span class="hl slc"># since we quote with &quot;&quot;</span></li>
<li id="n_540" class="hl">                <span class="hl kwc">substr</span><span class="hl opt">(</span><span class="hl kwb">$text</span><span class="hl opt">, </span><span class="hl kwb">$v_offset</span><span class="hl opt">, </span><span class="hl kwb">$v_len</span><span class="hl opt">) = </span><span class="hl sng">qq(&quot;</span><span class="hl ipl">$new_v</span><span class="hl sng">&quot;)</span><span class="hl opt">;</span></li>
<li id="n_541" class="hl">            <span class="hl opt">}</span></li>
<li id="n_542" class="hl">        <span class="hl opt">}</span></li>
<li id="n_543" class="hl">        <span class="hl kwb">$ret</span><span class="hl opt">.=</span><span class="hl kwb">$text</span><span class="hl opt">;</span></li>
<li id="n_544" class="hl">    <span class="hl opt">}, </span><span class="hl sng">&quot;tagname, tokenpos, text&quot;</span><span class="hl opt">);</span></li>
<li id="n_545" class="hl">    <span class="hl kwb">$p</span><span class="hl opt">-&gt;</span><span class="hl kwd">parse</span><span class="hl opt">(</span><span class="hl kwb">$html</span><span class="hl opt">);</span></li>
<li id="n_546" class="hl">    <span class="hl kwb">$p</span><span class="hl opt">-&gt;</span><span class="hl kwc">eof</span><span class="hl opt">;</span></li>
<li id="n_547" class="hl"></li>
<li id="n_548" class="hl">    <span class="hl kwa">return </span><span class="hl kwb">$ret</span><span class="hl opt">;</span></li>
<li id="n_549" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_550" class="hl"></li>
<li id="n_551" class="hl"><span class="hl kwa">sub </span>pagefile <span class="hl opt">($) { </span><span class="hl slc">#{{{</span></li>
<li id="n_552" class="hl">    <span class="hl kwc">my </span><span class="hl kwb">$page</span><span class="hl opt">=</span><span class="hl kwc">shift</span><span class="hl opt">;</span></li>
<li id="n_553" class="hl"></li>
<li id="n_554" class="hl">    <span class="hl kwa">return </span><span class="hl sng">&quot;</span><span class="hl ipl">$config</span><span class="hl sng">{srcdir}/&quot;</span><span class="hl opt">.</span>htmlfn<span class="hl opt">(</span><span class="hl kwb">$page</span><span class="hl opt">);</span></li>
<li id="n_555" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_556" class="hl"></li>
<li id="n_557" class="hl"><span class="hl kwa">sub </span>htmlfn <span class="hl opt">($) { </span><span class="hl slc">#{{{</span></li>
<li id="n_558" class="hl">    <span class="hl kwa">return </span><span class="hl kwc">shift</span><span class="hl opt">().</span><span class="hl sng">&quot;.&quot;</span><span class="hl opt">.</span><span class="hl kwb">$config</span><span class="hl opt">{</span>htmlext<span class="hl opt">};</span></li>
<li id="n_559" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_560" class="hl"></li>
<li id="n_561" class="hl"><span class="hl kwc">my </span><span class="hl kwb">$aggregatelock</span><span class="hl opt">;</span></li>
<li id="n_562" class="hl"></li>
<li id="n_563" class="hl"><span class="hl kwa">sub </span>lockaggregate <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_564" class="hl">    <span class="hl slc"># Take an exclusive lock to prevent multiple concurrent aggregators.</span></li>
<li id="n_565" class="hl">    <span class="hl slc"># Returns true if the lock was aquired.</span></li>
<li id="n_566" class="hl">    <span class="hl kwa">if </span><span class="hl opt">(! -</span>d <span class="hl kwb">$config</span><span class="hl opt">{</span>wikistatedir<span class="hl opt">}) {</span></li>
<li id="n_567" class="hl">        <span class="hl kwc">mkdir</span><span class="hl opt">(</span><span class="hl kwb">$config</span><span class="hl opt">{</span>wikistatedir<span class="hl opt">});</span></li>
<li id="n_568" class="hl">    <span class="hl opt">}</span></li>
<li id="n_569" class="hl">    <span class="hl kwc">open</span><span class="hl opt">(</span><span class="hl kwb">$aggregatelock</span><span class="hl opt">, </span><span class="hl sng">&#39;&gt;&#39;</span><span class="hl opt">, </span><span class="hl sng">&quot;</span><span class="hl ipl">$config</span><span class="hl sng">{wikistatedir}/aggregatelock&quot;</span><span class="hl opt">) ||</span></li>
<li id="n_570" class="hl">        error <span class="hl opt">(</span><span class="hl sng">&quot;cannot open to </span><span class="hl ipl">$config</span><span class="hl sng">{wikistatedir}/aggregatelock: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">);</span></li>
<li id="n_571" class="hl">    <span class="hl kwa">if </span><span class="hl opt">(! </span><span class="hl kwc">flock</span><span class="hl opt">(</span><span class="hl kwb">$aggregatelock</span><span class="hl opt">, </span><span class="hl num">2 </span><span class="hl opt">| </span><span class="hl num">4</span><span class="hl opt">)) { </span><span class="hl slc"># LOCK_EX | LOCK_NB</span></li>
<li id="n_572" class="hl">        <span class="hl kwc">close</span><span class="hl opt">(</span><span class="hl kwb">$aggregatelock</span><span class="hl opt">) || </span>error<span class="hl opt">(</span><span class="hl sng">&quot;failed closing aggregatelock: </span><span class="hl ipl">$!</span><span class="hl sng">&quot;</span><span class="hl opt">);</span></li>
<li id="n_573" class="hl">        <span class="hl kwa">return </span><span class="hl num">0</span><span class="hl opt">;</span></li>
<li id="n_574" class="hl">    <span class="hl opt">}</span></li>
<li id="n_575" class="hl">    <span class="hl kwa">return </span><span class="hl num">1</span><span class="hl opt">;</span></li>
<li id="n_576" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_577" class="hl"></li>
<li id="n_578" class="hl"><span class="hl kwa">sub </span>unlockaggregate <span class="hl opt">() { </span><span class="hl slc">#{{{</span></li>
<li id="n_579" class="hl">    <span class="hl kwa">return </span><span class="hl kwc">close</span><span class="hl opt">(</span><span class="hl kwb">$aggregatelock</span><span class="hl opt">) </span><span class="hl kwa">if </span><span class="hl kwb">$aggregatelock</span><span class="hl opt">;</span></li>
<li id="n_580" class="hl">    <span class="hl kwa">return</span><span class="hl opt">;</span></li>
<li id="n_581" class="hl"><span class="hl opt">} </span><span class="hl slc">#}}}</span></li>
<li id="n_582" class="hl"></li>
<li id="n_583" class="hl"><span class="hl num">1</span></li>
</ol></code></pre></td></tr></table>
</div> <!-- class=content -->
<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.46.0</a>) at 2025-05-20 03:25:07 +0000</div>
</div> <!-- id=cgit -->
</body>
</html>
