βŒˆβŒ‹ βŽ‡ branch:  freshcode


Check-in [5cc3693148]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Moved projects_ and index_ output into template/ Made pagination() reusable into aux.php
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5cc36931482c57740de7778f48070442a198b3f8
User & Date: mario 2014-07-11 10:40:24
Context
2014-07-11
12:52
Move JS functionality out of template/header, to prepare for tags-editing check-in: fcd926fc7e user: mario tags: trunk
10:40
Moved projects_ and index_ output into template/ Made pagination() reusable into aux.php check-in: 5cc3693148 user: mario tags: trunk
01:31
Remove [x] And it's not spam checkbox (not descriptive, and faux form catcher sufficient). Use <code> and <var> for some field docs. check-in: cb5d669cec user: mario tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to aux.php.

192
193
194
195
196
197
198
















199
200
201
202
203
204
205
      </span>
HTML;
}
function social_share_count($num) {
    return empty($num) ? "" : "<var class=social-share-count>$num</var>";
}


















// CSRF token, only for logged-in users though
// Here they're mainly to prevent remotely initiated requests for other users here, not general form nonces
function csrf($probe=false) {

    // Tokens are stored in session, reusable, but only for an hour
    $store = & $_SESSION[__FUNCTION__];







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
      </span>
HTML;
}
function social_share_count($num) {
    return empty($num) ? "" : "<var class=social-share-count>$num</var>";
}



/**
 * Write out pseudo pagination links.
 * This is just appended no matter the actually available entries.
 * The db() queries themselves handle the LIMIT/OFFSET, depending on a page param.
 *
 */
function pagination($page_no, $GET_param="n") {
    print "<p class=pagination-links> Β»";
    foreach (range($page_no-2, $page_no+9) as $n) if ($n > 0) {
        print " <a " . ($n==$page_no ? "class=current " : ""). "href=\"?n=$n\">$n</a> ";
    }
    print "Β« </p>";
}


// CSRF token, only for logged-in users though
// Here they're mainly to prevent remotely initiated requests for other users here, not general form nonces
function csrf($probe=false) {

    // Tokens are stored in session, reusable, but only for an hour
    $store = & $_SESSION[__FUNCTION__];

Changes to lib/input.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
 /**
  * api: php
  * title: Input $_REQUEST wrappers
  * type: interface
  * description: Encapsulates input variable superglobals for easy sanitization access
  * version: 2.7
  * revision: $Id$
  * license: Public Domain
  * depends: php:filter, php >5.0, html_purifier
  * config: <const name="INPUT_DIRECT" type="multi" value="disallow" multi="disallow|raw|log" description="filter method for direct $_REQUEST[var] access" />
  *         <const name="INPUT_QUIET" type="bool" value="0" multi="0=report all|1=no notices|2=no warnings" description="suppress access and behaviour notices" />
  * throws: E_USER_NOTICE, E_USER_WARNING, OutOfBoundsException
  *






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
 /**
  * api: php
  * title: Input $_REQUEST wrappers
  * type: interface
  * description: Encapsulates input variable superglobals for easy sanitization access
  * version: 2.8
  * revision: $Id$
  * license: Public Domain
  * depends: php:filter, php >5.0, html_purifier
  * config: <const name="INPUT_DIRECT" type="multi" value="disallow" multi="disallow|raw|log" description="filter method for direct $_REQUEST[var] access" />
  *         <const name="INPUT_QUIET" type="bool" value="0" multi="0=report all|1=no notices|2=no warnings" description="suppress access and behaviour notices" />
  * throws: E_USER_NOTICE, E_USER_WARNING, OutOfBoundsException
  *
100
101
102
103
104
105
106












107
108
109
110
111
112
113
  * needed - not all input can be filtered anyway. This way an audit handler
  * could always attach there - when desired.
  *
  * The goal is not to coerce, but encourage security via API *simplicity*.
  *
  */














/**
 * Handler name for direct $_REQUEST["array"] access.
 *
 *   "raw" = reports with warning,
 *   "disallow" = throws an exception
 */







>
>
>
>
>
>
>
>
>
>
>
>







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  * needed - not all input can be filtered anyway. This way an audit handler
  * could always attach there - when desired.
  *
  * The goal is not to coerce, but encourage security via API *simplicity*.
  *
  */


/**
 * Project-specific identifiers.
 *
 * Since `input` is an overly generic name, one might wish to wrap it up if
 * there's an identifier conflict. (Remember; namespaces aren't taxonomies.)
 *
 */
#namespace filter;
#use \ArrayObject, \Countable, \Iterator, \OutOfBoundsException;
#use \HTMLPurifier;


/**
 * Handler name for direct $_REQUEST["array"] access.
 *
 *   "raw" = reports with warning,
 *   "disallow" = throws an exception
 */
152
153
154
155
156
157
158

159

160
161
162
163
164
165
166
167
168


169
170
171
172
173
174
175
176

177

178
179
180
181
182
183
184
185
186
187


188
189
190
191
192
193
194
195
196






197








198
199
200
201
202
203
204
205
206
     * Categories: [e]=escape, [w]=whitelist, [b]=blacklist, [s]=sanitize, [v]=validate
     *
     */


    
    /**

     * [w]

     * Integer.
     *
     */
    function _int($data) {
        return (int)$data;
    }

    /**
     * [w]


     * Float.
     *
     */
    function _float($data) {
        return (float)$data;
    }
    
    /**

     * [w]

     * Alphanumeric strings.
     * (e.g. var names, letters and numbers, may contain international letters)
     *
     */
    function _name($data) {
        return preg_replace("/\W+/u", "", $data);
    }

    /**
     * [w]


     * Identifiers with underscores and dots,
     * like "xvar.1_2.x"
     *
     */
    function _id($data) {
        return preg_replace("#(^[^a-z_]+)|[^\w\d_.]+|([^\w_]$)#i", "", $data);
    }
    
    /**






     * [w]








     * Flow text with whitespace,
     * minimal interpunction allowed.
     *
     */
    function _words($data, $extra="") {
        return preg_replace("/[^\w\d\s,._\-+$extra]+/u", " ", strip_tags($data));
    }

    /**







>
|
>








|
>
>








>
|
>









|
>
>

<





|

>
>
>
>
>
>
|
>
>
>
>
>
>
>
>

|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
     * Categories: [e]=escape, [w]=whitelist, [b]=blacklist, [s]=sanitize, [v]=validate
     *
     */


    
    /**
     * @type    cast
     * @sample  22
     *
     * Integer.
     *
     */
    function _int($data) {
        return (int)$data;
    }

    /**
     * @type    cast
     * @sample  3.14159
     *
     * Float.
     *
     */
    function _float($data) {
        return (float)$data;
    }
    
    /**
     * @type    white, strip
     * @sample  "_foo123"
     *
     * Alphanumeric strings.
     * (e.g. var names, letters and numbers, may contain international letters)
     *
     */
    function _name($data) {
        return preg_replace("/\W+/u", "", $data);
    }

    /**
     * @type    white, strip
     * @sample  "xvar.1_2.x"
     *
     * Identifiers with underscores and dots,

     *
     */
    function _id($data) {
        return preg_replace("#(^[^a-z_]+)|[^\w\d_.]+|([^\w_]$)#i", "", $data);
    }

    /**
     * @type    white, strip
     * @sample  "tag-name-123"
     *
     * Alphanumeric strings with dashes. Commonly used for slugs.
     * Consecutive dashes and underscores are compacted.
     *
     */
    function _slug($data) {
        return preg_replace("/[^\w-]+|^[^a-z]+|[^\w]+$|(?<=[-_])[-_]+/", "", strtolower($s));
    }
    
    /**
     * @type    white, strip
     * @sample  "Hello - World. Foo + 3, Bar."
     * 
     * Flow text with whitespace,
     * with minimal interpunction allowed (optional parameter).
     *
     */
    function _words($data, $extra="") {
        return preg_replace("/[^\w\d\s,._\-+$extra]+/u", " ", strip_tags($data));
    }

    /**

Changes to page_index.php.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 *   β†’ RSS/Atom links for update feed comprised of all projects.
 *
 */


$header_add = "<link rel=alternate type=application/rss+xml href=/feed/xfer.rss>\n<link rel=alternate type=application/atom+xml href=/feed/xfer.atom>";
include("template/header.php");
include("template/sidebar_index.php");
?> <section id=main> <?php


// query projects
$page_no = $_GET->int->range…1…100["n"];
$releases = db("
    SELECT *
      FROM release_versions
     WHERE flag < 5
     LIMIT 40
    OFFSET 40*?
", $page_no - 1);


// show
foreach ($releases as $entry) {

    // HTML escaping and some autogenerated fields
    prepare_output($entry);
    // Callback for varexpression function calls in heredoc
    $_ = "trim";
    
    // Output
    print <<<HTML
      <article class=project>
        <h3>
            <a href="projects/$entry[name]">$entry[title]
            <em class=version>$entry[version]</em></a>
            <span class=links>
                <span class=published_date>$entry[formatted_date]</span>
                <a href="$entry[homepage]"><img src="img/home.png" width=20 height=20 border=0 align=middle></a>
                <a href="$entry[download]"><img src="img/disk.png" width=20 height=20 border=0 align=middle></a>
            </span>
        </h3>
        <a href="$entry[homepage]"><img class=preview src="$entry[image]" align=right width=120 height=90 border=0></a>
        <p class="description trimmed">$entry[description]</p>
        <p class="release-notes trimmed"><b>$entry[scope]:</b> $entry[changes]</p>
        <p class=tags><img src="img/tag.png" width=30 align=middle height=22 border=0><a class=license>$entry[license]</a>{$_(wrap_tags($entry["tags"]))}</p>
      </article>
HTML;

}


// add pseudo pagination (do not actually count available entries)
print "<p class=pagination-links> Β»";
foreach (range($page_no-2, $page_no+9) as $n) if ($n > 0) {
    print " <a " . ($n==$page_no ? "class=current " : ""). "href=\"?n=$n\">$n</a> ";
}
print "Β« </p>";


include("template/bottom.php");





?>







|














|

<
<

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
|
|
<
<
|
<

<


<
<
<
<

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42


43


44


















45
46


47
48


49

50

51
52




53
 *   β†’ RSS/Atom links for update feed comprised of all projects.
 *
 */


$header_add = "<link rel=alternate type=application/rss+xml href=/feed/xfer.rss>\n<link rel=alternate type=application/atom+xml href=/feed/xfer.atom>";
include("template/header.php");
include("template/index_sidebar.php");
?> <section id=main> <?php


// query projects
$page_no = $_GET->int->range…1…100["n"];
$releases = db("
    SELECT *
      FROM release_versions
     WHERE flag < 5
     LIMIT 40
    OFFSET 40*?
", $page_no - 1);


// Convert entries to HTML output
foreach ($releases as $entry) {


    prepare_output($entry);


    include("template/index_project.php");


















}



// Add pseudo pagination for further pages.
pagination($page_no, "n");






include("template/bottom.php");





?>

Changes to page_projects.php.

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
     WHERE name = ?
       AND NOT deleted
     LIMIT 1
", $name);

// Show sidebar + long project description
if ($entry = $releases->fetch()) {
    
    // Output
    prepare_output($entry);
    $_ = "trim";
    include("template/projects_sidebar.php");
    include("template/projects_description.php");
}



#-- Retrieve all released versions
$releases = db("
    SELECT *, MAX(t_changed)
      FROM release
     WHERE name = ?
       AND flag < 5
       AND NOT deleted
  GROUP BY version
  ORDER BY t_published DESC, t_changed DESC
", $name);

?> <article class=release-list>  <h3>Recent Releases</h3> <?php
while ($entry = $releases->fetch()) {
    
    // Output
    prepare_output($entry);
    include("template/projects_release_entry.php");
}
?> </article> <?php


// html tail
include("template/bottom.php");



?>







<
<

<

















|

<
<












34
35
36
37
38
39
40


41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60


61
62
63
64
65
66
67
68
69
70
71
72
     WHERE name = ?
       AND NOT deleted
     LIMIT 1
", $name);

// Show sidebar + long project description
if ($entry = $releases->fetch()) {


    prepare_output($entry);

    include("template/projects_sidebar.php");
    include("template/projects_description.php");
}



#-- Retrieve all released versions
$releases = db("
    SELECT *, MAX(t_changed)
      FROM release
     WHERE name = ?
       AND flag < 5
       AND NOT deleted
  GROUP BY version
  ORDER BY t_published DESC, t_changed DESC
", $name);

?> <article class=release-list>  <h4>Recent Releases</h4> <?php
while ($entry = $releases->fetch()) {


    prepare_output($entry);
    include("template/projects_release_entry.php");
}
?> </article> <?php


// html tail
include("template/bottom.php");



?>

Changes to page_submit.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
<?php
/**
 * api: freshcode
 * type: page
 * title: Submit/edit project or release
 * description: Single-page edit form for projects and their releases
 * version: 0.6.0
 * category: form
 * license: AGPLv3
 * 
 *
 * Prepares the submission form,
 * handles database preparation
 * and merges in previous release entries.
 *

 *
 */



// Form field names
$form_fields = array(










<
|
<
|

>







1
2
3
4
5
6
7
8
9
10

11

12
13
14
15
16
17
18
19
20
21
<?php
/**
 * api: freshcode
 * type: page
 * title: Submit/edit project or release
 * description: Single-page edit form for projects and their releases
 * version: 0.6.0
 * category: form
 * license: AGPLv3
 * 

 * Prepares the submission form. On POST checks a few constraints,

 * but UPDATE itself is handled by release::update() and ::store().
 *
 * Tags: http://aehlke.github.io/tag-it/
 *
 */



// Form field names
$form_fields = array(
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

// Retrieve existing project data in DB.
$data = release::latest($name);
$is_new = empty($data);

// Else create empty form value defaults in $data
if ($is_new) {
    $data = array_combine($form_fields, array_fill(0, count($form_fields), ""));
    $data["name"] = $name;
    $data["submitter"] = $_SESSION["name"];
}


// Project entry can be locked for editing by specific OpenIDs.
if (!release::permission($data, $_SESSION["openid"])) {







|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

// Retrieve existing project data in DB.
$data = release::latest($name);
$is_new = empty($data);

// Else create empty form value defaults in $data
if ($is_new) {
    $data = array_fill_keys($form_fields, "");
    $data["name"] = $name;
    $data["submitter"] = $_SESSION["name"];
}


// Project entry can be locked for editing by specific OpenIDs.
if (!release::permission($data, $_SESSION["openid"])) {

Name change from template/sidebar_index.php to template/index_sidebar.php.






1







2
3
4
5
6
7
8
9
10
11
12
13
14
15















 <aside id=sidebar>

    <section class="article-links untrimmed">
        <h5>linux.com Software</h5>
        <?php  include("template/feed.linuxcom.htm");  ?>
    </section>

    <section class="article-links trimmed">
        <h5>reddit /r/linux</h5>
        <?php  include("template/feed.reddit.htm");  ?>
    </section>

 </aside>

>
>
>
>
>
|
>
>
>
>
>
>
>














>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
/**
 * type: template
 * title: frontpage feeds
 * description: Outputs #sidebar on frontage, containing template/feed.*.htm
 *
 * The feed.*.htm files are regularily updated
 * by cron.daily/newsfeeeds. Thus does not need
 * further processing here.
 *
 */

?>

 <aside id=sidebar>

    <section class="article-links untrimmed">
        <h5>linux.com Software</h5>
        <?php  include("template/feed.linuxcom.htm");  ?>
    </section>

    <section class="article-links trimmed">
        <h5>reddit /r/linux</h5>
        <?php  include("template/feed.reddit.htm");  ?>
    </section>

 </aside>

Changes to template/projects_description.php.

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17


18
19
20
21
22
23
24
<?php
/**
 * api: include
 * type: template
 * title: Project description
 * description: Displays title, version, description, tags, homepage + download button

 *
 * Each projects/ page description contains
 *
 *   β†’ Headline of project title and current version
 *   β†’ Screenshot image
 *   β†’ Description
 *   β†’ Tag list (tags, license, state)
 *   β†’ [Homepage] and [Download] link buttons
 *
 */




print <<<PROJECT
      <article class=project>

        <h3>
            <a href="projects/$entry[name]">
               $entry[title]






>











>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
/**
 * api: include
 * type: template
 * title: Project description
 * description: Displays title, version, description, tags, homepage + download button
 * depends: wrap_tags
 *
 * Each projects/ page description contains
 *
 *   β†’ Headline of project title and current version
 *   β†’ Screenshot image
 *   β†’ Description
 *   β†’ Tag list (tags, license, state)
 *   β†’ [Homepage] and [Download] link buttons
 *
 */


$_ = "trim";

print <<<PROJECT
      <article class=project>

        <h3>
            <a href="projects/$entry[name]">
               $entry[title]

Changes to template/projects_release_entry.php.

1
2
3
4
5
6

7
8
9
10
11
12
13
<?php
/**
 * api: include
 * type: template
 * title: Project version entry
 * description: Displays a release, with scope and changes

 *
 * Shows versioning history of projects/
 *   β†’ Date and Version
 *   β†’ Scope and Changes
 *
 * This template, obviously, gets iterated over to output all
 * release entries.






>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
/**
 * api: include
 * type: template
 * title: Project version entry
 * description: Displays a release, with scope and changes
 * depends: strftime
 *
 * Shows versioning history of projects/
 *   β†’ Date and Version
 *   β†’ Scope and Changes
 *
 * This template, obviously, gets iterated over to output all
 * release entries.

Changes to template/projects_sidebar.php.

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
<?php
/**
 * api: include
 * type: template
 * title: Sidebar links for project
 * description: Shows project URLs, submitter, submit/ and flag/ link, social bookmarks

 *
 * Creates #sidebar with four <section>s:
 *   β†’ Project links (homepage, download, other URLs)
 *   β†’ Submitter with gravatar/identicon
 *   β†’ Submission edit button, and flag/ link
 *   β†’ Social sharing links and β˜… star count.
 *
 */



print <<<SIDEBAR
      <aside id=sidebar>
         <section>
           <h5>Links</h5>
           <a href="$entry[homepage]"><img src="img/home.png" width=11 height=11> Project Website</a><br>
           <a href="$entry[download]"><img src="img/disk.png" width=11 height=11> Download</a><br>






>









>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/**
 * api: include
 * type: template
 * title: Sidebar links for project
 * description: Shows project URLs, submitter, submit/ and flag/ link, social bookmarks
 * depends: proj_links, social_share_count, social_share_links
 *
 * Creates #sidebar with four <section>s:
 *   β†’ Project links (homepage, download, other URLs)
 *   β†’ Submitter with gravatar/identicon
 *   β†’ Submission edit button, and flag/ link
 *   β†’ Social sharing links and β˜… star count.
 *
 */

$_ = "trim";

print <<<SIDEBAR
      <aside id=sidebar>
         <section>
           <h5>Links</h5>
           <a href="$entry[homepage]"><img src="img/home.png" width=11 height=11> Project Website</a><br>
           <a href="$entry[download]"><img src="img/disk.png" width=11 height=11> Download</a><br>