5 <meta name=
"generator" content=
"pandoc">
6 <meta name=
"viewport" content=
"width=device-width, initial-scale=1.0, user-scalable=yes">
7 <title>Shaarli - Download CSS styles from an OPML list
</title>
8 <style type=
"text/css">code{white-space: pre;}
</style>
10 <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
12 <style type=
"text/css">
13 table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
14 margin:
0; padding:
0; vertical-align: baseline; border: none; }
15 table.sourceCode { width:
100%; line-height:
100%; }
16 td.lineNumbers { text-align: right; padding-right:
4px; padding-left:
4px; color: #aaaaaa; border-right:
1px solid #aaaaaa; }
17 td.sourceCode { padding-left:
5px; }
18 code
> span.kw { color: #
007020; font-weight: bold; }
19 code
> span.dt { color: #
902000; }
20 code
> span.dv { color: #
40a070; }
21 code
> span.bn { color: #
40a070; }
22 code
> span.fl { color: #
40a070; }
23 code
> span.ch { color: #
4070a0; }
24 code
> span.st { color: #
4070a0; }
25 code
> span.co { color: #
60a0b0; font-style: italic; }
26 code
> span.ot { color: #
007020; }
27 code
> span.al { color: #ff0000; font-weight: bold; }
28 code
> span.fu { color: #
06287e; }
29 code
> span.er { color: #ff0000; font-weight: bold; }
31 <link rel=
"stylesheet" href=
"github-markdown.css">
34 <div id=
"local-sidebar">
36 <li><a href=
"Home.html">Home
</a></li>
39 <li><a href=
"Download.html">Download
</a></li>
40 <li><a href=
"Server-requirements.html">Server requirements
</a></li>
41 <li><a href=
"Server-configuration.html">Server configuration
</a></li>
42 <li><a href=
"Shaarli-configuration.html">Shaarli configuration
</a></li>
44 <li><a href=
"Usage.html">Usage
</a>
46 <li><a href=
"Sharing-button.html">Sharing button
</a> (bookmarklet)
</li>
47 <li><a href=
"Firefox-share.html">Firefox share
</a></li>
48 <li><a href=
"RSS-feeds.html">RSS feeds
</a></li>
52 <li><a href=
"Backup,-restore,-import-and-export.html">Backup, restore, import and export
</a></li>
53 <li><a href=
"Copy-an-existing-installation-over-SSH-and-serve-it-locally.html">Copy an existing installation over SSH and serve it locally
</a></li>
54 <li><a href=
"Download-CSS-styles-from-an-OPML-list.html">Download CSS styles from an OPML list
</a></li>
55 <li><a href=
"Datastore-hacks.html">Datastore hacks
</a></li>
57 <li><a href=
"Troubleshooting.html">Troubleshooting
</a></li>
58 <li><a href=
"Development.html">Development
</a>
60 <li><a href=
"GnuPG-signature.html">GnuPG signature
</a></li>
61 <li><a href=
"Coding-guidelines.html">Coding guidelines
</a></li>
62 <li><a href=
"Directory-structure.html">Directory structure
</a></li>
63 <li><a href=
"3rd-party-libraries.html">3rd party libraries
</a></li>
64 <li><a href=
"Plugin-System.html">Plugin System
</a></li>
65 <li><a href=
"Security.html">Security
</a></li>
66 <li><a href=
"Static-analysis.html">Static analysis
</a></li>
67 <li><a href=
"Theming.html">Theming
</a></li>
68 <li><a href=
"Unit-tests.html">Unit tests
</a></li>
72 <li><a href=
"FAQ.html">FAQ
</a></li>
73 <li><a href=
"Community-&-Related-software.html">Community
& Related software
</a></li>
74 <li><a href=
"TODO.html">TODO
</a></li>
78 <h1 id=
"download-css-styles-from-an-opml-list">Download CSS styles from an OPML list
</h1>
79 <h3 id=
"download-css-styles-for-shaarlis-listed-in-an-opml-file">Download CSS styles for shaarlis listed in an opml file
</h3>
80 <p>Example php script:
</p>
81 <pre class=
"sourceCode php"><code class=
"sourceCode php"><!----
<span class=
"ot">?
</span>php --
>
82 <!---- Copyright
<span class=
"ot">(
</span>c
<span class=
"ot">)
</span> <span class=
"dv">2014</span> Nicolas Delsaux
<span class=
"ot">(
</span>https
<span class=
"ot">:
</span><span class=
"co">//github.com/Riduidel) --
></span>
83 <!---- License: zlib
<span class=
"ot">(
</span>http:
<span class=
"co">//www.gzip.org/zlib/zlib_license.html) --
></span>
85 <span class=
"co">/**
</span>
86 <span class=
"co"> * Source: https://github.com/Riduidel
</span>
87 <span class=
"co"> * Download css styles for shaarlis listed in an opml file
</span>
88 <span class=
"co"> */
</span>
89 <span class=
"fu">define
</span><span class=
"ot">(
</span><span class=
"st">"SHAARLI_RSS_OPML
"</span><span class=
"ot">,
</span> <span class=
"st">"https://www.ecirtam.net/shaarlirss/custom/people.opml
"</span><span class=
"ot">);
</span>
91 <span class=
"fu">define
</span><span class=
"ot">(
</span><span class=
"st">"THEMES_TEMP_FOLDER
"</span><span class=
"ot">,
</span> <span class=
"st">"new_themes
"</span><span class=
"ot">);
</span>
93 <span class=
"kw">if
</span><span class=
"ot">(
</span>!
<span class=
"fu">file_exists
</span><span class=
"ot">(
</span><span class=
"kw">THEMES_TEMP_FOLDER
</span><span class=
"ot">))
</span> {
94 <span class=
"fu">mkdir
</span><span class=
"ot">(
</span><span class=
"kw">THEMES_TEMP_FOLDER
</span><span class=
"ot">);
</span>
97 <span class=
"kw">function
</span> siteUrl
<span class=
"ot">(
</span><span class=
"kw">$pathInSite
</span><span class=
"ot">)
</span> {
98 <span class=
"kw">$indexPos
</span> =
<span class=
"fu">strpos
</span><span class=
"ot">(
</span><span class=
"kw">$pathInSite
</span><span class=
"ot">,
</span> <span class=
"st">"index.php
"</span><span class=
"ot">);
</span>
99 <span class=
"kw">if
</span><span class=
"ot">(
</span>!
<span class=
"kw">$indexPos
</span><span class=
"ot">)
</span> {
100 <span class=
"kw">return
</span> <span class=
"kw">$pathInSite
</span><span class=
"ot">;
</span>
101 }
<span class=
"kw">else
</span> {
102 <span class=
"kw">return
</span> <span class=
"fu">substr
</span><span class=
"ot">(
</span><span class=
"kw">$pathInSite
</span><span class=
"ot">,
</span> <span class=
"dv">0</span><span class=
"ot">,
</span> <span class=
"kw">$indexPos
</span><span class=
"ot">);
</span>
106 <span class=
"kw">function
</span> createShaarliHashFromOPMLL
<span class=
"ot">(
</span><span class=
"kw">$opmlFile
</span><span class=
"ot">)
</span> {
107 <span class=
"kw">$result
</span> =
<span class=
"fu">array
</span><span class=
"ot">();
</span>
108 <span class=
"kw">$opml
</span> =
<span class=
"fu">file_get_contents
</span><span class=
"ot">(
</span><span class=
"kw">$opmlFile
</span><span class=
"ot">);
</span>
109 <span class=
"kw">$opmlXml
</span> =
<span class=
"fu">simplexml_load_string
</span><span class=
"ot">(
</span><span class=
"kw">$opml
</span><span class=
"ot">);
</span>
110 <span class=
"kw">$outlineElements
</span> =
<span class=
"kw">$opmlXml
</span>-
>xpath
<span class=
"ot">(
</span><span class=
"st">"body/outline
"</span><span class=
"ot">);
</span>
111 <span class=
"kw">foreach
</span><span class=
"ot">(
</span><span class=
"kw">$outlineElements
</span> <span class=
"kw">as
</span> <span class=
"kw">$site
</span><span class=
"ot">)
</span> {
112 <span class=
"kw">$siteUrl
</span> = siteUrl
<span class=
"ot">(
</span><span class=
"dt">(string)
</span> <span class=
"kw">$site
</span><span class=
"ot">[
</span><span class=
"st">'htmlUrl
'</span><span class=
"ot">]);[](
</span>.html
<span class=
"ot">)
</span>
113 <span class=
"kw">$result
</span><span class=
"ot">[
</span><span class=
"kw">$siteUrl
</span><span class=
"ot">]
</span>=
<span class=
"ot">(
</span><span class=
"dt">(string)
</span> <span class=
"kw">$site
</span><span class=
"ot">[
</span><span class=
"st">'text
'</span><span class=
"ot">]);[](
</span>.html
<span class=
"ot">)
</span>
115 <span class=
"kw">return
</span> <span class=
"kw">$result
</span><span class=
"ot">;
</span>
118 <span class=
"kw">function
</span> getSiteFolder
<span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">)
</span> {
119 <span class=
"kw">$domain
</span> =
<span class=
"fu">parse_url
</span><span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">,
</span> <span class=
"kw">PHP_URL_HOST
</span><span class=
"ot">);
</span>
120 <span class=
"kw">return
</span> <span class=
"kw">THEMES_TEMP_FOLDER
</span>.
<span class=
"st">"/
"</span>.
<span class=
"fu">str_replace
</span><span class=
"ot">(
</span><span class=
"st">".
"</span><span class=
"ot">,
</span> <span class=
"st">"_
"</span><span class=
"ot">,
</span> <span class=
"kw">$domain
</span><span class=
"ot">);
</span>
123 <span class=
"kw">function
</span> get_http_response_code
<span class=
"ot">(
</span><span class=
"kw">$theURL
</span><span class=
"ot">)
</span> {
124 <span class=
"kw">$headers
</span> =
<span class=
"fu">get_headers
</span><span class=
"ot">(
</span><span class=
"kw">$theURL
</span><span class=
"ot">);
</span>
125 <span class=
"kw">return
</span> <span class=
"fu">substr
</span><span class=
"ot">(
</span><span class=
"kw">$headers
</span><span class=
"ot">[
</span><span class=
"dv">0</span><span class=
"ot">],
</span> <span class=
"dv">9</span><span class=
"ot">,
</span> <span class=
"dv">3</span><span class=
"ot">);[](
</span>.html
<span class=
"ot">)
</span>
128 <span class=
"co">/**
</span>
129 <span class=
"co"> * This makes the code PHP-
5 only (particularly the call to
"get_headers
")
</span>
130 <span class=
"co"> */
</span>
131 <span class=
"kw">function
</span> copyUserStyleFrom
<span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">,
</span> <span class=
"kw">$name
</span><span class=
"ot">,
</span> <span class=
"kw">$knownStyles
</span><span class=
"ot">)
</span> {
132 <span class=
"kw">$userStyle
</span> =
<span class=
"kw">$url
</span>.
<span class=
"st">"inc/user.css
"</span><span class=
"ot">;
</span>
133 <span class=
"kw">if
</span><span class=
"ot">(
</span><span class=
"fu">in_array
</span><span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">,
</span> <span class=
"kw">$knownStyles
</span><span class=
"ot">))
</span> {
134 <span class=
"co">// TODO add log message
</span>
135 }
<span class=
"kw">else
</span> {
136 <span class=
"kw">$statusCode
</span> = get_http_response_code
<span class=
"ot">(
</span><span class=
"kw">$userStyle
</span><span class=
"ot">);
</span>
137 <span class=
"kw">if
</span><span class=
"ot">(
</span><span class=
"fu">intval
</span><span class=
"ot">(
</span><span class=
"kw">$statusCode
</span><span class=
"ot">)
</span><<span class=
"dv">300</span><span class=
"ot">)
</span> {
138 <span class=
"kw">$styleSheet
</span> =
<span class=
"fu">file_get_contents
</span><span class=
"ot">(
</span><span class=
"kw">$userStyle
</span><span class=
"ot">);
</span>
139 <span class=
"kw">$siteFolder
</span> = getSiteFolder
<span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">);
</span>
140 <span class=
"kw">if
</span><span class=
"ot">(
</span>!
<span class=
"fu">file_exists
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span><span class=
"ot">))
</span> {
141 <span class=
"fu">mkdir
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span><span class=
"ot">);
</span>
143 <span class=
"kw">if
</span><span class=
"ot">(
</span>!
<span class=
"fu">file_exists
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/user.css
'</span><span class=
"ot">))
</span> {
144 <span class=
"co">// Copy stylesheet
</span>
145 <span class=
"fu">file_put_contents
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/user.css
'</span><span class=
"ot">,
</span> <span class=
"kw">$styleSheet
</span><span class=
"ot">);
</span>
147 <span class=
"kw">if
</span><span class=
"ot">(
</span>!
<span class=
"fu">file_exists
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/README.md
'</span><span class=
"ot">))
</span> {
148 <span class=
"co">// Then write a readme.md file
</span>
149 <span class=
"fu">file_put_contents
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/README.md
'</span><span class=
"ot">,
</span>
150 <span class=
"st">"User style from
"</span>.
<span class=
"kw">$name
</span>.
<span class=
"st">"</span><span class=
"kw">\n
</span><span class=
"st">"</span>
151 .
<span class=
"st">"=============================
"</span>
152 .
<span class=
"st">"</span><span class=
"kw">\n\n
</span><span class=
"st">"</span>
153 .
<span class=
"st">"This stylesheet was downloaded from
"</span>.
<span class=
"kw">$userStyle
</span>.
<span class=
"st">" on
"</span>.
<span class=
"fu">date
</span><span class=
"ot">(
</span><span class=
"kw">DATE_RFC822
</span><span class=
"ot">)
</span>
154 <span class=
"ot">);
</span>
156 <span class=
"kw">if
</span><span class=
"ot">(
</span>!
<span class=
"fu">file_exists
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/config.ini
'</span><span class=
"ot">))
</span> {
157 <span class=
"co">// Write a config file containing useful informations
</span>
158 <span class=
"fu">file_put_contents
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/config.ini
'</span><span class=
"ot">,
</span>
159 <span class=
"st">"site_url=
"</span>.
<span class=
"kw">$url
</span>.
<span class=
"st">"</span><span class=
"kw">\n
</span><span class=
"st">"</span>
160 .
<span class=
"st">"site_name=
"</span>.
<span class=
"kw">$name
</span>.
<span class=
"st">"</span><span class=
"kw">\n
</span><span class=
"st">"</span>
161 <span class=
"ot">);
</span>
163 <span class=
"kw">if
</span><span class=
"ot">(
</span>!
<span class=
"fu">file_exists
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/home.png
'</span><span class=
"ot">))
</span> {
164 <span class=
"co">// And finally copy generated thumbnail
</span>
165 <span class=
"kw">$homeThumb
</span> =
<span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/home.png
'</span><span class=
"ot">;
</span>
166 <span class=
"fu">file_put_contents
</span><span class=
"ot">(
</span><span class=
"kw">$siteFolder
</span>.
<span class=
"st">'/home.png
'</span><span class=
"ot">,
</span> <span class=
"fu">file_get_contents
</span><span class=
"ot">(
</span>getThumbnailUrl
<span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">)));
</span>
168 <span class=
"fu">echo
</span> <span class=
"st">'Theme have been downloaded from
<a href=
"'</span>.
<span class=
"kw">$url
</span>.
<span class=
"st">'">'</span>.
<span class=
"kw">$url
</span>.
<span class=
"st">'</a
> into
'</span>.
<span class=
"kw">$siteFolder
</span>
169 .
<span class=
"st">'. It looks like
<img src=
"'</span>.
<span class=
"kw">$homeThumb
</span>.
<span class=
"st">'"><br/
>'</span><span class=
"ot">;
</span>
174 <span class=
"kw">function
</span> getThumbnailUrl
<span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">)
</span> {
175 <span class=
"kw">return
</span> <span class=
"st">'http://api.webthumbnail.org/?url=
'</span>.
<span class=
"kw">$url
</span><span class=
"ot">;
</span>
178 <span class=
"kw">function
</span> copyUserStylesFrom
<span class=
"ot">(
</span><span class=
"kw">$urlToNames
</span><span class=
"ot">,
</span> <span class=
"kw">$knownStyles
</span><span class=
"ot">)
</span> {
179 <span class=
"kw">foreach
</span><span class=
"ot">(
</span><span class=
"kw">$urlToNames
</span> <span class=
"kw">as
</span> <span class=
"kw">$url
</span> =
> <span class=
"kw">$name
</span><span class=
"ot">)
</span> {
180 copyUserStyleFrom
<span class=
"ot">(
</span><span class=
"kw">$url
</span><span class=
"ot">,
</span> <span class=
"kw">$name
</span><span class=
"ot">,
</span> <span class=
"kw">$knownStyles
</span><span class=
"ot">);
</span>
184 <span class=
"co">/**
</span>
185 <span class=
"co"> * Reading directory list, courtesy of http://www.laughing-buddha.net/php/dirlist/
</span>
186 <span class=
"co"> *
</span><span class=
"kw">@param
</span><span class=
"co"> </span><span class=
"kw">directory
</span><span class=
"co"> the directory we want to list files of
</span>
187 <span class=
"co"> *
</span><span class=
"kw">@return
</span><span class=
"co"> a simple array containing the list of absolute file paths. Notice that current file (
".
") and parent one(
"..
")
</span>
188 <span class=
"co"> * are not listed here
</span>
189 <span class=
"co"> */
</span>
190 <span class=
"kw">function
</span> getDirectoryList
<span class=
"ot">(
</span><span class=
"kw">$directory
</span><span class=
"ot">)
</span> {
191 <span class=
"kw">$realPath
</span> =
<span class=
"fu">realpath
</span><span class=
"ot">(
</span><span class=
"kw">$directory
</span><span class=
"ot">);
</span>
192 <span class=
"co">// create an array to hold directory list
</span>
193 <span class=
"kw">$results
</span> =
<span class=
"fu">array
</span><span class=
"ot">();
</span>
194 <span class=
"co">// create a handler for the directory
</span>
195 <span class=
"kw">$handler
</span> =
<span class=
"fu">opendir
</span><span class=
"ot">(
</span><span class=
"kw">$directory
</span><span class=
"ot">);
</span>
196 <span class=
"co">// open directory and walk through the filenames
</span>
197 <span class=
"kw">while
</span> <span class=
"ot">(
</span><span class=
"kw">$file
</span> =
<span class=
"fu">readdir
</span><span class=
"ot">(
</span><span class=
"kw">$handler
</span><span class=
"ot">))
</span> {
198 <span class=
"co">// if file isn
't this directory or its parent, add it to the results
</span>
199 <span class=
"kw">if
</span> <span class=
"ot">(
</span><span class=
"kw">$file
</span> !=
<span class=
"st">".
"</span> && <span class=
"kw">$file
</span> !=
<span class=
"st">"..
"</span><span class=
"ot">)
</span> {
200 <span class=
"kw">$results
</span><span class=
"ot">[
</span> =
<span class=
"fu">realpath
</span><span class=
"ot">(
</span><span class=
"kw">$realPath
</span> .
<span class=
"st">"/
"</span> .
<span class=
"kw">$file
</span><span class=
"ot">);](
</span>-=-
<span class=
"fu">realpath
</span><span class=
"ot">(
</span><span class=
"kw">$realPath
</span>-.-
<span class=
"st">"/
"</span>-.-
<span class=
"kw">$file
</span><span class=
"ot">);
</span>.html
<span class=
"ot">)
</span>
203 <span class=
"co">// tidy up: close the handler
</span>
204 <span class=
"fu">closedir
</span><span class=
"ot">(
</span><span class=
"kw">$handler
</span><span class=
"ot">);
</span>
205 <span class=
"co">// done!
</span>
206 <span class=
"kw">return
</span> <span class=
"kw">$results
</span><span class=
"ot">;
</span>
209 <span class=
"co">/**
</span>
210 <span class=
"co"> * Start in themes folder and look in all subfolders for config.ini files.
</span>
211 <span class=
"co"> * These config.ini files allow us not to download styles again and again
</span>
212 <span class=
"co"> */
</span>
213 <span class=
"kw">function
</span> findKnownStyles
<span class=
"ot">()
</span> {
214 <span class=
"kw">$result
</span> =
<span class=
"fu">array
</span><span class=
"ot">();
</span>
215 <span class=
"kw">$subFolders
</span> = getDirectoryList
<span class=
"ot">(
</span><span class=
"st">"themes
"</span><span class=
"ot">);
</span>
216 <span class=
"kw">foreach
</span><span class=
"ot">(
</span><span class=
"kw">$subFolders
</span> <span class=
"kw">as
</span> <span class=
"kw">$folder
</span><span class=
"ot">)
</span> {
217 <span class=
"kw">$configFile
</span> =
<span class=
"kw">$folder
</span>.
<span class=
"st">"/config.ini
"</span><span class=
"ot">;
</span>
218 <span class=
"kw">if
</span><span class=
"ot">(
</span><span class=
"fu">file_exists
</span><span class=
"ot">(
</span><span class=
"kw">$configFile
</span><span class=
"ot">))
</span> {
219 <span class=
"kw">$iniParameters
</span> =
<span class=
"fu">parse_ini_file
</span><span class=
"ot">(
</span><span class=
"kw">$configFile
</span><span class=
"ot">);
</span>
220 <span class=
"fu">array_push
</span><span class=
"ot">(
</span><span class=
"kw">$result
</span><span class=
"ot">,
</span> <span class=
"kw">$iniParameters
</span><span class=
"ot">[
</span><span class=
"st">'site_url
'</span><span class=
"ot">]);[](
</span>.html
<span class=
"ot">)
</span>
223 <span class=
"kw">return
</span> <span class=
"kw">$result
</span><span class=
"ot">;
</span>
226 <span class=
"kw">$knownStyles
</span> = findKnownStyles
<span class=
"ot">();
</span>
227 copyUserStylesFrom
<span class=
"ot">(
</span>createShaarliHashFromOPMLL
<span class=
"ot">(
</span><span class=
"kw">SHAARLI_RSS_OPML
</span><span class=
"ot">),
</span> <span class=
"kw">$knownStyles
</span><span class=
"ot">);
</span>
229 <!---
<span class=
"ot">?
</span> ----
></code></pre>