index.cgi 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #!/bin/bash
  2. #
  3. # Server for the Blog application in CGI!
  4. #
  5. # Updates will have to be done locally (no web editing), but the wiki will
  6. # make up for it.
  7. #
  8. # Copyright 2015 K. Zimmermann - https://notabug.org/kzimmermann
  9. #
  10. # This program is free software: you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License as published by
  12. # the Free Software Foundation, either version 3 of the License, or
  13. # (at your option) any later version.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License
  21. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. #
  23. #-- Built-in variables: --#
  24. # if you wish to use markdown, download the script and reference it in
  25. # the variable below. Otherwise only plain paragraphs are supported.
  26. # Remember to reference the *full* path to the script!
  27. markdown="./Markdown.pl"
  28. # change this to a name that no one could guess (leave the .db extension).
  29. db="main.db"
  30. date=""
  31. #-- /Variables --#
  32. #-- Predefined functions: --#
  33. # Fetcher of content from the database:
  34. fetcher() {
  35. # Pass $1 as the element you want and $2 the id of the blog entry!
  36. echo -e "$(sqlite3 $db "SELECT $1 FROM articles WHERE id=$2")"
  37. }
  38. create_paragraphs() {
  39. # Pass $1 as the full text to be parsed.
  40. final="
  41. <p>
  42. "
  43. final="$final"$(echo "$1" | sed 's/^$/\<\/p\>\n\<p\>/g' )
  44. final=$final"
  45. </p>"
  46. echo "$final"
  47. }
  48. # Markdown formatting
  49. parse_markdown() {
  50. # pass content to be parsed as $1
  51. if [[ -n "$markdown" ]]
  52. then
  53. echo "$1" | $markdown
  54. else
  55. # fall back to plain paragraphs:
  56. create_paragraphs "$1"
  57. fi
  58. }
  59. #-- Query string parsing session --#
  60. # Assume a query of http://site.com/?article&id=X
  61. # If we're searching, this query will come up: (...)/?search=TOKEN
  62. page=$(echo "$QUERY_STRING" | cut -d "&" -f 1 | cut -d "=" -f 1)
  63. id=$(echo "$QUERY_STRING" | cut -d "&" -f 2 | cut -d "=" -f 2)
  64. #-- Page selection routines --#
  65. #
  66. # To add a new permanent page, simply add a new entry like this before
  67. # the * ) line:
  68. #
  69. # "page_url" )
  70. # title="Page title goes here"
  71. # content="$($markdown content_of_page.md)"
  72. # ;;
  73. #
  74. # You will need an external page file for this, preferably in Markdown.
  75. #
  76. case "$page" in
  77. "" )
  78. title="Home"
  79. content="$($markdown home.md)"
  80. ;;
  81. "articles")
  82. title="Article database"
  83. content="
  84. <p>
  85. Articles curated by my mind in its full inspiration. May be hard to
  86. come by depending on the week, but I'll try my best to put something
  87. in at least every week to say what's going on my mind.
  88. </p>
  89. <form action=\"/\" method=\"GET\">
  90. <input type=\"text\" name=\"search\" placeholder=\"Search for an article\" />
  91. <input type=\"submit\" value=\"Search\" /> <br />
  92. </form>
  93. <p>
  94. You may also want to grab my <a href=\"feed.rss\">RSS feed</a> just in
  95. case if there are delays in the updates and stuff. I'm still working
  96. on it, though.
  97. </p>
  98. <ul>
  99. "
  100. articles_links=$(sqlite3 $db "SELECT id FROM articles ORDER BY pubdate DESC")
  101. for article in $articles_links
  102. do
  103. article_title=$(sqlite3 $db "SELECT title FROM articles WHERE id=$article")
  104. article_pubdate=$(sqlite3 $db "SELECT pubdate FROM articles WHERE id=$article")
  105. content=$content"<li><a href=\"?article\&id=$article\">$article_title</a> - $article_pubdate</li>
  106. "
  107. done
  108. content=$content"</ul>
  109. "
  110. ;;
  111. "article")
  112. title=$(fetcher "title" $id)
  113. # Sanity check if article does not exist:
  114. if [ -z "$title" ]
  115. then
  116. title="Article not found"
  117. content="<p>This article does not exist.</p>
  118. <p>You may want to try the <a href=\"?articles\">full article list</a>.</p>
  119. "
  120. else
  121. content=$(fetcher "body" $id)
  122. content=$(parse_markdown "$content")
  123. date="<p>Last updated on "$(fetcher "pubdate" $id)"</p>"
  124. # Increment page views by +1
  125. sqlite3 $db "
  126. UPDATE articles SET pageviews =
  127. (SELECT pageviews + 1 FROM articles WHERE id = $id)
  128. WHERE id = $id;
  129. "
  130. fi
  131. ;;
  132. "search" )
  133. title="Search results for $id"
  134. results="$(
  135. sqlite3 $db "SELECT id FROM articles WHERE title LIKE '%$id%' OR body LIKE '%$id%'"
  136. )"
  137. if [[ -z "$results" ]]
  138. then
  139. content="
  140. <p>
  141. Sorry, no results found for '$id'.
  142. </p>
  143. "
  144. else
  145. content="
  146. <p>
  147. Articles matching '$id':
  148. </p>
  149. <ul>
  150. "
  151. for match in $results
  152. do
  153. content=$content"<li><a href=\"?article\&id=$match\">
  154. $(sqlite3 $db "SELECT title FROM articles WHERE id=$match")
  155. </a></li>
  156. "
  157. done
  158. fi
  159. content=$content"</ul>
  160. <form action=\"/\" method=\"GET\">
  161. <input type=\"text\" name=\"search\" placeholder=\"Search for an article\" />
  162. <input type=\"submit\" value=\"Search\" /> <br />
  163. </form>
  164. "
  165. ;;
  166. "contact")
  167. title="Contact me"
  168. content="$($markdown contact.md)"
  169. ;;
  170. "privacypolicy" )
  171. title="Privacy policy"
  172. content="$($markdown privacypolicy.md)"
  173. ;;
  174. * )
  175. title="Page not Found"
  176. content="<p>
  177. The page you were looking for has not been found.
  178. </p>
  179. <p>
  180. You might want to check out the <a href=\"/wiki\">Wiki</a> or go to the home page.
  181. </p>
  182. <p>You searched for: $page</p>
  183. "
  184. ;;
  185. esac
  186. #-- Serve the content! --#
  187. printf "Content-Type: text/html\nCharset: UTF-8\n\n"
  188. content="$(echo "$content" | tr -d '\n')"
  189. # It's hard to find the perfect character to use in sed. It has to be 1-byte
  190. # long, and not used in common speech. ^ is not perfect, but works well so
  191. # far.
  192. cat template.html | sed "s^{{title}}^$title^g" |
  193. sed "s^{{content}}^$content^g" |
  194. sed "s^{{date}}^$date^g"