cookutils view web/cooker.cgi @ rev 894

cook: fix copy() -> cook_copy_folders() for repeated copying; web/cooker.cgi: manage packages with '+' in the name; web/style.css: get styles from mirror1.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Fri Mar 24 17:29:16 2017 +0200 (2017-03-24)
parents eff71eaaee4f
children fe29568da760
line source
1 #!/bin/sh
2 #
3 # SliTaz Cooker CGI/web interface.
4 #
6 . /usr/lib/slitaz/httphelper.sh
8 [ -f "/etc/slitaz/cook.conf" ] && . /etc/slitaz/cook.conf
9 [ -f "cook.conf" ] && . ./cook.conf
11 # The same wok as cook.
12 wok="$WOK"
14 # Cooker DB files.
15 activity="$CACHE/activity"
16 commits="$CACHE/commits"
17 cooklist="$CACHE/cooklist"
18 cookorder="$CACHE/cookorder"
19 command="$CACHE/command"; touch $command
20 blocked="$CACHE/blocked"
21 broken="$CACHE/broken"
22 cooknotes="$CACHE/cooknotes"
23 cooktime="$CACHE/cooktime"
24 wokrev="$CACHE/wokrev"
26 # Path to markdown to html convertor
27 if [ -n "$(which cmark 2>/dev/null)" ]; then
28 md2html="$(which cmark) --smart -e table -e strikethrough -e autolink -e tagfilter"
29 elif [ -x "./cmark" ]; then
30 md2html="./cmark --smart -e table -e strikethrough -e autolink -e tagfilter"
31 elif [ -n "$(which sundown 2>/dev/null)" ]; then
32 md2html=$(which sundown)
33 elif [ -x "./sundown" ]; then
34 md2html="./sundown"
35 fi
37 # We're not logged and want time zone to display correct server date.
38 export TZ=$(cat /etc/TZ)
41 # HTML page header. Pages can be customized with a separated header.html file
43 page_header() {
44 echo -e 'Content-Type: text/html; charset=UTF-8\n'
45 if [ -f "header.html" ]; then
46 cat header.html
47 else
48 cat <<EOT
49 <!DOCTYPE html>
50 <html lang="en">
51 <head>
52 <meta charset="UTF-8">
53 <meta name="viewport" content="width=device-width, initial-scale=1.0">
54 <title>SliTaz Cooker</title>
55 <link rel="shortcut icon" href="favicon.ico">
56 <link rel="stylesheet" href="style.css">
57 <script src="prism.js"></script>
58 <link rel="stylesheet" href="prism.css">
59 <link rel="alternate" type="application/rss+xml" title="Cooker Feed" href="?rss">
60 <meta name="robots" content="nofollow">
61 </head>
62 <body>
64 <div id="header">
65 <div id="logo"></div>
66 <h1><a href="cooker.cgi">SliTaz Cooker</a></h1>
67 </div>
68 EOT
69 fi
70 }
73 # HTML page footer. Pages can be customized with a separated footer.html file
75 page_footer() {
76 if [ -f "footer.html" ]; then
77 cat footer.html
78 else
79 cat <<EOT
80 </div>
82 <div id="footer">
83 <a href="http://www.slitaz.org/">SliTaz Website</a>
84 <a href="cooker.cgi">Cooker</a>
85 <a href="doc/cookutils/cookutils.html">Documentation</a>
86 </div>
88 </body>
89 </html>
90 EOT
91 fi
92 }
95 not_found() {
96 local file="${1#$PKGS/}"; file="${file#$LOGS/}"; file="${file#$WOK/}"
97 echo "HTTP/1.1 404 Not Found"
98 page_header
99 echo "<div id='content'><h2>Not Found</h2>"
100 case $2 in
101 pkg)
102 echo "<p>The requested package <b>$(basename "$(dirname "$file")")</b> was not found on this server.</p>" ;;
103 *)
104 echo "<p>The requested file <b>$file</b> was not found on this server.</p>" ;;
105 esac
106 page_footer
107 }
110 manage_modified() {
111 local file="$1" option="$2" nul day mon year time hh mm ss date_s
112 if [ ! -f "$file" ]; then
113 if [ "$option" == 'silently-absent' ]; then
114 echo "HTTP/1.1 404 Not Found"
115 return
116 else
117 not_found "$file" "$2"
118 exit
119 fi
120 fi
121 [ "$option" == 'no-last-modified' ] && return
122 if [ -n "$HTTP_IF_MODIFIED_SINCE" ]; then
123 echo "$HTTP_IF_MODIFIED_SINCE" | \
124 while read nul day mon year time nul; do
125 case $mon in
126 Jan) mon='01';; Feb) mon='02';; Mar) mon='03';; Apr) mon='04';;
127 May) mon='05';; Jun) mon='06';; Jul) mon='07';; Aug) mon='08';;
128 Sep) mon='09';; Oct) mon='10';; Nov) mon='11';; Dec) mon='12';;
129 esac
130 hh=$(echo $time | cut -d: -f1)
131 mm=$(echo $time | cut -d: -f2)
132 ss=$(echo $time | cut -d: -f3)
133 date_s=$(date -ud "$year$mon$day$hh$mm.$ss" +%s)
134 # if [ "$date_s" -ge "$(date -ur "$file" +%s)" ]; then
135 # echo -e 'HTTP/1.1 304 Not Modified\n'
136 # exit
137 # fi
138 # TODO: improve caching control
139 done
140 fi
141 echo "Last-Modified: $(date -Rur "$file" | sed 's|UTC|GMT|')"
142 echo "Cache-Control: public, max-age=3600"
143 }
146 case "$QUERY_STRING" in
147 recook=*)
148 case "$HTTP_USER_AGENT" in
149 *SliTaz*)
150 grep -qs "^$(GET recook)$" $CACHE/recook-packages ||
151 echo "$(GET recook)" >> $CACHE/recook-packages
152 esac
153 echo -e "Location: ${HTTP_REFERER:-${REQUEST_URI%\?*}}\n"
154 exit
155 ;;
157 poke)
158 touch $CACHE/cooker-request
159 echo -e "Location: ${HTTP_REFERER:-${REQUEST_URI%\?*}}\n"
160 exit
161 ;;
163 src*)
164 file=$(busybox httpd -d "$SRC/$(GET src)")
165 manage_modified "$file"
166 content_type='application/octet-stream'
167 case $file in
168 *.tar.gz) content_type='application/x-compressed-tar' ;;
169 *.tar.bz2) content_type='application/x-bzip-compressed-tar' ;;
170 *.tar.xz) content_type='application/x-xz-compressed-tar' ;;
171 *.tar.lzma) content_type='application/x-lzma-compressed-tar' ;;
172 *.zip) content_type='application/zip' ;;
173 esac
174 echo "Content-Type: $content_type"
175 echo "Content-Length: $(stat -c %s "$file")"
176 filename=$(basename "$file")
177 echo "Content-Disposition: attachment; filename=\"$filename\"" # Note, no conversion '+' -> '%2B' here
178 echo
180 cat "$file"
181 exit
182 ;;
184 download*)
185 file="$PKGS/$(GET download)"
186 manage_modified "$file"
187 content_type='application/octet-stream'
188 case $file in
189 *.txt|*.conf|*/README|*/receipt)
190 content_type='text/plain; charset=UTF-8' ;;
191 *.css) content_type='text/css; charset=UTF-8' ;;
192 *.htm|*.html) content_type='text/html; charset=UTF-8' ;;
193 *.js) content_type='application/javascript; charset=UTF-8' ;;
194 *.desktop) content_type='application/x-desktop; charset=UTF-8' ;;
195 *.png) content_type='image/png' ;;
196 *.gif) content_type='image/gif' ;;
197 *.svg) content_type='image/svg+xml' ;;
198 *.jpg|*.jpeg) content_type='image/jpeg' ;;
199 *.sh|*.cgi) content_type='application/x-shellscript' ;;
200 *.gz) content_type='application/gzip' ;;
201 *.ico) content_type='image/vnd.microsoft.icon' ;;
202 *.tazpkg) content_type='application/x-tazpkg' ;;
203 esac
205 echo "Content-Type: $content_type"
206 echo "Content-Length: $(stat -c %s "$file")"
207 filename=$(basename "$file")
208 echo "Content-Disposition: inline; filename=\"$filename\"" # Note, no conversion '+' -> '%2B' here
209 echo
211 cat "$file"
212 exit
213 ;;
215 rss)
216 echo -e 'Content-Type: application/rss+xml\n'
217 ;;
219 stuff*)
220 file="$wok/$(GET stuff)"
221 manage_modified "$file"
222 ;;
224 pkg=*|receipt=*|description=*|files=*|log=*|man=*|doc=*|info=*)
225 type=${QUERY_STRING%%=*}
226 pkg=$(GET $type)
227 case "$type" in
228 description)
229 manage_modified "$wok/$pkg/receipt" 'no-last-modified'
230 manage_modified "$wok/$pkg/description.txt" 'silently-absent'
231 ;;
232 log)
233 manage_modified "$wok/${pkg%%.log*}/receipt" 'no-last-modified'
234 manage_modified "$LOGS/$pkg"
235 ;;
236 *)
237 manage_modified "$wok/$pkg/receipt" pkg
238 ;;
239 esac
240 ;;
242 esac
245 # RSS feed generator
246 if [ "$QUERY_STRING" == 'rss' ]; then
247 pubdate=$(date -R)
248 cat <<EOT
249 <?xml version="1.0" encoding="utf-8" ?>
250 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
251 <channel>
252 <title>SliTaz Cooker</title>
253 <description>The SliTaz packages cooker feed</description>
254 <link>$COOKER_URL</link>
255 <lastBuildDate>$pubdate</lastBuildDate>
256 <pubDate>$pubdate</pubDate>
257 <atom:link href="http://cook.slitaz.org/?rss" rel="self" type="application/rss+xml" />
258 EOT
259 for rss in $(ls -lt $FEEDS/*.xml | head -n 12); do
260 cat $rss | sed 's|<guid|& isPermaLink="false"|g;s|</pubDate| GMT&|g'
261 done
262 cat <<EOT
263 </channel>
264 </rss>
265 EOT
266 exit 0
267 fi
270 #
271 # Functions
272 #
275 # Unpack to stdout
277 docat() {
278 case "$1" in
279 *gz) zcat ;;
280 *bz2) bzcat ;;
281 *xz) xzcat ;;
282 *) cat
283 esac < $1
284 }
287 # Tiny texinfo browser
289 info2html() {
290 sed \
291 -e 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g' \
292 -e 's|^\* \(.*\)::|* <a href="#\1">\1</a> |' \
293 -e 's|\*note \(.*\)::|<a href="#\1">\1</a>|' \
294 -e '/^File: / s|(dir)|Top|g' \
295 -e '/^File: / s|Next: \([^,]*\)|<a class="button" href="#\1">Next: \1</a>|' \
296 -e '/^File: / s|Prev: \([^,]*\)|<a class="button" href="#\1">Prev: \1</a>|' \
297 -e '/^File: / s|Up: \([^,]*\)|<a class="button" href="#\1">Up: \1</a>|' \
298 -e '/^File: / s|^.* Node: \([^,]*\), *\(.*\)$|<pre id="\1">\2|' \
299 -e '/^<pre id=/ s|^\([^>]*>\)\(<a[^>]*>Next: [^,]*\), *\(<a[^>]*>Prev: [^,]*\), *\(<a[^>]*>Up: .*\)|\1 \3 \4 \2|' \
300 -e '/^Tag Table:$/,/^End Tag Table$/d' \
301 -e '/INFO-DIR/,/^END-INFO-DIR/d' \
302 -e "s|https*://[^>),'\"\`’ ]*|<a href=\"&\">&</a>|g" \
303 -e "s|ftp://[^>),\"\` ]*|<a href=\"&\">&</a>|g" \
304 -e 's|^\* Menu:|<b>Menu:</b>|' \
305 -e "s|^|</pre>|"
306 }
309 # Put some colors in log and DB files.
311 syntax_highlighter() {
312 case $1 in
313 log)
314 # If variables not defined - define them with some rare values
315 : ${_src=#_#_#}
316 : ${_install=#_#_#}
317 : ${_fs=#_#_#}
318 : ${_stuff=#_#_#}
319 sed -e 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' \
320 -e 's#OK$#<span class="span-ok">OK</span>#g' \
321 -e 's#Done$#<span class="span-ok">Done</span>#g' \
322 -e 's#done$#<span class="span-ok">done</span>#g' \
323 -e 's#\([^a-z]\)ok$#\1<span class="span-ok">ok</span>#g' \
324 -e 's#\([^a-z]\)yes$#\1<span class="span-ok">yes</span>#g' \
325 -e 's#\([^a-z]\)no$#\1<span class="span-no">no</span>#g' \
326 \
327 -e 's#\( \[Y[nm/]\?\] n\)$# <span class="span-no">\1</span>#g' \
328 -e 's#\( \[N[ym/]\?\] y\)$# <span class="span-ok">\1</span>#g' \
329 -e 's#(NEW) $#<span class="span-red">(NEW) </span>#g' \
330 \
331 -e 's#.*(pkg/local).*#<span class="span-ok">\0</span>#g' \
332 -e 's#.*(web/cache).*#<span class="span-no">\0</span>#g' \
333 \
334 -e 's#error$#<span class="span-red">error</span>#g' \
335 -e 's#ERROR:#<span class="span-red">ERROR:</span>#g' \
336 -e 's#Error#<span class="span-red">Error</span>#g' \
337 \
338 -e 's#^.*[Ff]ailed.*#<span class="span-red">\0</span>#g' \
339 -e 's#^.*[Ff]atal.*#<span class="span-red">\0</span>#g' \
340 -e 's#^.*[Nn]ot found.*#<span class="span-red">\0</span>#g' \
341 -e 's#^.*[Nn]o such file.*#<span class="span-red">\0</span>#g' \
342 \
343 -e 's#WARNING:#<span class="span-red">WARNING:</span>#g' \
344 -e 's#warning:#<span class="span-no">warning:</span>#g' \
345 -e 's#error:#<span class="span-no">error:</span>#g' \
346 -e 's#missing#<span class="span-no">missing</span>#g' \
347 \
348 -e 's#^.* will not .*#<span class="span-no">\0</span>#' \
349 -e 's!^Hunk .* succeeded at .*!<span class="span-no">\0</span>!' \
350 -e 's#^.* Warning: .*#<span class="span-no">\0</span>#' \
351 \
352 -e "s#^Executing:\([^']*\).#<span class='sh-val'>\0</span>#" \
353 -e "s#^Making.*#<span class='sh-val'>\0</span>#" \
354 -e "s#^====\([^']*\).#<span class='span-line'>\0</span>#g" \
355 -e "s#^[a-zA-Z0-9]\([^']*\) :: #<span class='span-sky'>\0</span>#g" \
356 -e "s#ftp://[^ '\"]*#<a href='\0'>\0</a>#g" \
357 -e "s#http://[^ '\"]*#<a href='\0'>\0</a>#g" \
358 -e "s|$_src|<span class='var'>\${src}</span>|g;
359 s|$_install|<span class='var'>\${install}</span>|g;
360 s|$_fs|<span class='var'>\${fs}</span>|g;
361 s|$_stuff|<span class='var'>\${stuff}</span>|g" \
362 -e "s|\[91m|<span style='color: #F00'>|;
363 s|\[92m|<span style='color: #080'>|;
364 s|\[93m|<span style='color: #FF0'>|;
365 s|\[94m|<span style='color: #00F'>|;
366 s|\[95m|<span style='color: #808'>|;
367 s|\[96m|<span style='color: #088'>|;
368 s|\[39m|</span>|;"
369 ;;
371 files)
372 sed \
373 -e "s|\[[01];31m|<span style='color: #F00'>|g;
374 s|\[[01];32m|<span style='color: #080'>|g;
375 s|\[[01];33m|<span style='color: #FF0'>|g;
376 s|\[[01];34m|<span style='color: #00F'>|g;
377 s|\[[01];35m|<span style='color: #808'>|g;
378 s|\[[01];36m|<span style='color: #088'>|g;
379 s|\[[01];0m|<span style='color: #333'>|g;
380 s|\[0m|</span>|g;"
381 ;;
383 activity)
384 sed s"#^\([^']* : \)#<span class='log-date'>\0</span>#"g
385 ;;
386 esac
387 }
390 show_code() {
391 echo "<pre><code class=\"language-$1\">"
392 sed 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g'
393 echo '</code></pre>'
394 }
397 # Latest build pkgs.
399 list_packages() {
400 cd $PKGS
401 ls -1t *.tazpkg | head -n 20 | \
402 while read file; do
403 echo -n $(TZ=UTC stat -c '%y' $PKGS/$file | cut -d. -f1 | sed s/:[0-9]*$//)
404 echo " : $file"
405 done
406 }
409 # Optional full list button
411 more_button() {
412 [ $(wc -l < ${3:-$CACHE/$1}) -gt ${4:-12} ] &&
413 echo "<a class='button r' href='?file=$1'>$2</a>"
414 }
417 # Show the running command and its progression
419 running_command() {
420 local state="Not running"
421 if [ -s "$command" ]; then
422 state="$(cat $command)"
423 set -- $(grep "^$state" $cooktime)
424 if [ -n "$1" ]; then
425 state="$state $((($(date +%s)-$3)*100/$2))%"
426 [ $2 -gt 300 ] && state="$state (should end $(date -u -d @$(($2+$3))))"
427 fi
428 fi
429 echo $state
430 }
433 datalist() {
434 (
435 cd $wok
437 ls | awk '
438 BEGIN{printf("<datalist id=\"packages\">")}
439 {printf("<option>%s</option>",$1)}
440 END {printf("</datalist>")}
441 '
442 )
443 }
446 summary() {
447 log="$1"
448 pkg="$(basename ${log%%.log*})"
449 if [ -f "$log" ]; then
450 if grep -q "cook:$pkg$" $command; then
451 echo "<pre>The Cooker is currently building: $pkg</pre>"
452 fi
453 if fgrep -q "Summary for:" $log; then
454 echo "<pre>"
455 sed '/^Summary for:/,$!d' $log | sed /^$/d | syntax_highlighter log
456 echo "</pre>"
457 fi
459 if fgrep -q "Debug information" $log; then
460 echo '<pre>'
461 sed '/^Debug information/,$!d' $log | sed /^$/d | \
462 if [ -n "$2" ]; then
463 syntax_highlighter log | \
464 sed 's|\([0-9][0-9]*\):|<a href="#l\1">\1</a>:|'
465 else
466 sed 's|^[0-9][0-9]*:||' | syntax_highlighter log
467 fi
468 echo '</pre>'
469 fi
470 else
471 [ -n "$pkg" -a -d "$wok/$pkg" ] && echo "<pre>No log for $pkg</pre>"
472 fi
473 }
476 pkg_info() {
477 local log cmd active bpkg
478 log=$LOGS/$pkg.log
479 cmd=${QUERY_STRING%%=*}
480 echo '<div id="info">'
481 active=''; [ "$cmd" == 'receipt' -o "$cmd" == 'stuff' ] && active=' active'
482 echo "<a class='button green$active' href='?receipt=${pkg//+/%2B}'>receipt &amp; stuff</a>"
484 unset WEB_SITE WANTED
485 bpkg=$pkg
486 . $wok/$pkg/receipt
488 [ -n "$WANTED" ] && bpkg="${WANTED%% *}" # see locale-* with multiple WANTED
490 [ -n "$WEB_SITE" ] &&
491 echo "<a class='button sky' href='$WEB_SITE'>web site</a>"
493 if [ -f "$wok/$pkg/taz/$PACKAGE-$VERSION/receipt" ]; then
494 active=''; [ "$cmd" == 'files' ] && active=' active'
495 echo "<a class='button khaki$active' href='?files=${pkg//+/%2B}'>files</a>"
497 unset EXTRAVERSION
498 . $wok/$pkg/taz/$PACKAGE-$VERSION/receipt
500 if [ -f $wok/$pkg/taz/$PACKAGE-$VERSION/description.txt ]; then
501 active=''; [ "$cmd" == 'description' ] && active=' active'
502 echo "<a class='button brown$active' href='?description=${pkg//+/%2B}'>description</a>"
503 fi
505 if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg ]; then
506 echo "<a class='button gold' href='?download=${PACKAGE//+/%2B}-${VERSION//+/%2B}${EXTRAVERSION//+/%2B}.tazpkg'>download</a>"
507 fi
509 if [ -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg ]; then
510 echo "<a class='button gold' href='?download=${PACKAGE//+/%2B}-${VERSION//+/%2B}${EXTRAVERSION//+/%2B}-${ARCH//+/%2B}.tazpkg'>download</a>"
511 fi
512 fi
514 [ -n "$TARBALL" ] && [ -s "$SRC/$TARBALL" ] &&
515 echo "<a class='button yellow' href='?src=${TARBALL//+/%2B}'>source</a>"
517 [ -x ./man2html ] &&
518 if [ -d $wok/$bpkg/install/usr/man ] ||
519 [ -d $wok/$bpkg/install/usr/share/man ] ||
520 [ -d $wok/$bpkg/taz/*/fs/usr/man ] ||
521 [ -d $wok/$bpkg/taz/*/fs/usr/share/man ]; then
522 active=''; [ "$cmd" == 'man' ] && active=' active'
523 echo "<a class='button plum$active' href='?man=${bpkg//+/%2B}'>man</a>"
524 fi
526 if [ -d $wok/$bpkg/install/usr/doc ] ||
527 [ -d $wok/$bpkg/install/usr/share/doc ] ||
528 [ -d $wok/$bpkg/taz/*/fs/usr/doc ] ||
529 [ -d $wok/$bpkg/taz/*/fs/usr/share/doc ]; then
530 active=''; [ "$cmd" == 'doc' ] && active=' active'
531 echo "<a class='button plum$active' href='?doc=${bpkg//+/%2B}'>doc</a>"
532 fi
534 if [ -d $wok/$bpkg/install/usr/info ] ||
535 [ -d $wok/$bpkg/install/usr/share/info ] ||
536 [ -d $wok/$bpkg/taz/*/fs/usr/info ] ||
537 [ -d $wok/$bpkg/taz/*/fs/usr/share/info ]; then
538 active=''; [ "$cmd" == 'info' ] && active=' active'
539 echo "<a class='button plum$active' href='?info=${bpkg//+/%2B}#Top'>info</a>"
540 fi
542 [ -n "$(echo $REQUEST_URI | sed 's|/[^/]*?pkg.*||')" ] ||
543 echo "<a class='button' href='ftp://${HTTP_HOST%:*}/${pkg//+/%2B}/'>browse</a>"
545 if [ -s "$log" ]; then
546 active=''; [ "$cmd" == 'log' ] && active=' active'
547 echo "<a class='button gray$active' href='?log=${pkg//+/%2B}.log'>logs</a>"
548 fi
550 echo '</div>'
551 }
556 #
557 # Load requested page
558 #
560 page_header
562 case "${QUERY_STRING}" in
563 pkg=*)
564 pkg=$(GET pkg)
565 log=$LOGS/$pkg.log
567 # Define cook variables for syntax highlighter
568 if [ -s "$WOK/$pkg/receipt" ]; then
569 . "$WOK/$pkg/receipt"
570 _wok='/home/slitaz/wok'
571 _src="$_wok/$pkg/source/$PACKAGE-$VERSION"
572 _install="$_wok/$pkg/install"
573 _fs="$_wok/$pkg/taz/$PACKAGE-$VERSION/fs"
574 _stuff="$_wok/$pkg/stuff"
575 fi
577 # Package info.
578 if [ -f "$wok/$pkg/receipt" ]; then
579 echo "<div id='content'>"
580 echo "<h2>Package: $pkg</h2>"
581 pkg_info
582 else
583 if [ $(ls $wok/*$pkg*/receipt 2>/dev/null | wc -l) -eq 0 ]; then
584 echo "<div id='content'><h2>Not Found</h2>"
585 echo "<p>The requested package <b>$pkg</b> was not found on this server.</p>"
586 else
587 echo "<div id='content'>"
588 ls $wok/$pkg/receipt >/dev/null 2>&1 || pkg="*$pkg*"
589 echo '<table class="zebra" style="width:100%">'
590 for i in $(cd $wok ; ls $pkg/receipt); do
591 pkg=$(dirname $i)
592 unset SHORT_DESC CATEGORY
593 . $wok/$pkg/receipt
594 cat <<EOT
595 <tr>
596 <td><a href="?pkg=$pkg">$pkg</a></td>
597 <td>$SHORT_DESC</td>
598 <td>$CATEGORY</td>
599 </tr>
600 EOT
601 done
602 echo '</table>'
603 unset pkg
604 fi
605 fi
607 # Check for a log file and display summary if it exists.
608 summary "$log"
610 # Display <Recook> button only for SliTaz web browser
611 if [ -f "$log" ]; then
612 case "$HTTP_USER_AGENT" in
613 *SliTaz*)
614 [ -f $CACHE/cooker-request ] && [ -n "$HTTP_REFERER" ] &&
615 echo "<a class=\"button\" href=\"?recook=$pkg\">Recook $pkg</a>"
616 ;;
617 esac
618 fi
619 ;;
621 log=*)
622 log=$(GET log)
623 logfile=$LOGS/$log
624 pkg=${log%.log*}
625 if [ -s "$logfile" ]; then
626 echo "<div id='content'>"
628 echo "<h2>Cook log $(stat -c %y $logfile | sed 's/:..\..*//')</h2>"
629 pkg_info
631 case $log in
632 *.log) baselog=$logfile ;;
633 *) baselog=${logfile%.*} ;;
634 esac
635 for i in $(ls -t $baselog $baselog.* 2>/dev/null); do
636 class=''; [ $i == $logfile ] && class=' gray'
637 j=$(basename "$i")
638 echo -n "<a class='button$class' href=\"?log=${j//+/%2B}\">"
639 echo "$(stat -c %y $i | cut -d: -f1,2)</a>"
640 done
642 summary "$logfile" links
644 cat $logfile | syntax_highlighter log | awk '
645 BEGIN { print "<pre class=\"log\">"; }
646 { printf("<a name=\"l%d\" href=\"#l%d\">%5d</a> %s\n", NR, NR, NR, $0); }
647 END { print "</pre>"; }
648 '
649 fi
650 ;;
652 file=*)
653 echo "<div id='content'>"
654 # Don't allow all files on the system for security reasons.
655 file=$(GET file)
656 case "$file" in
657 activity|cooknotes|cooklist)
658 [ "$file" == "cooklist" ] && \
659 nb="- Packages: $(cat $cooklist | wc -l)"
660 echo '<div id="content2">'
661 echo "<h2>DB: $file $nb</h2>"
662 echo '<ul class="activity">'
663 tac $CACHE/$file | syntax_highlighter activity | \
664 sed 's|^|<li>|; s|$|</li>|'
665 echo '</ul></div>'
666 ;;
668 broken)
669 nb=$(wc -l < $broken)
670 echo '<div id="content2">'
671 echo "<h2>DB: broken - Packages: $nb</h2>"
672 echo '<ul class="activity">'
673 cat $CACHE/$file | sort | \
674 sed "s#^[^']*#<a href='?pkg=\0'>\0</a>#g" | \
675 sed 's|^|<li>|; s|$|</li>|'
676 echo '</ul></div>'
677 ;;
679 *.log)
680 log=$LOGS/$file
681 name=$(basename $log)
682 echo "<h2>Log for: ${name%.log}</h2>"
683 if [ -f "$log" ]; then
684 if fgrep -q "Summary" $log; then
685 echo '<pre>'
686 grep -A 20 "^Summary" $log | sed /^$/d | \
687 syntax_highlighter log
688 echo '</pre>'
689 fi
690 echo '<pre>'
691 cat $log | syntax_highlighter log
692 echo '</pre>'
693 else
694 echo "<pre>No log file: $log</pre>"
695 fi
696 ;;
697 esac
698 ;;
700 stuff=*)
701 echo "<div id='content'>"
702 file=$(GET stuff)
703 pkg=${file%%/*}
704 if [ -f "$wok/$file" ]; then
705 echo "<h2>$file</h2>"
706 pkg_info
707 echo "<a class='button' href='?receipt=${pkg//+/%2B}'>receipt</a>"
709 ( cd $wok/$pkg ; find stuff -type f 2> /dev/null ) | sort | \
710 while read i ; do
711 class=''; [ "$pkg/$i" == "$file" ] && class=" green"
712 echo "<a class='button$class' href='?stuff=${pkg//+/%2B}/${i//+/%2B}'>$i</a>"
713 done
715 case $file in
716 *.desktop|*.theme) class="ini" ;;
717 *.patch|*.diff|*.u) class="diff" ;;
718 *.sh) class="bash" ;;
719 *.conf*)
720 class="bash"
721 [ -n "$(cut -c1 < $wok/$file | fgrep '[')" ] && class="ini"
722 ;;
723 *.pl) class="perl" ;;
724 *.c|*.h|*.awk) class="clike" ;;
725 *.svg) class="svg" ;;
726 *Makefile*) class="makefile" ;;
727 *.po|*.pot) class="bash" ;;
728 *.css) class="css" ;;
729 *.htm|*.html) class="html" ;;
730 *.js) class="js" ;;
731 *.txt) class="asciidoc" ;;
732 *)
733 case $(head -n1 $wok/$file) in
734 *!/bin/sh*|*!/bin/bash*) class="bash" ;;
735 esac
736 if [ -z "$class" -a "$(head -n1 $wok/$file | cut -b1)" == '#' ]; then
737 class="bash"
738 fi
739 if [ -z "$class" ]; then
740 # Follow Busybox restrictions. Search for non-printable chars
741 if [ $(tr -d '[:alnum:][:punct:][:blank:][:cntrl:]' < "$wok/$file" | wc -c) -gt 0 ]; then
742 raw="true"
743 fi
744 fi
745 ;;
746 esac
748 # Display image
749 case $file in
750 *.png|*.svg|*.jpg|*.jpeg|*.ico)
751 echo "<img src='?download=../wok/${file//+/%2B}' style='display: block; max-width: 100%; margin: auto'/>"
752 ;;
753 esac
755 # Display colored listing for all text-based documents (also for *.svg)
756 case $file in
757 *.png|*.jpg|*.jpeg|*.ico) ;;
758 *)
759 if [ -z "$raw" ]; then
760 cat $wok/$file | show_code $class
761 fi
762 ;;
763 esac
765 # Display hex dump for binary files
766 if [ -n "$raw" ]; then
767 hexdump -C $wok/$file | show_code $class
768 fi
769 else
770 echo "<pre>File '$file' absent!</pre>"
771 fi
772 ;;
774 receipt=*)
775 echo "<div id='content'>"
776 pkg=$(GET receipt)
777 echo "<h2>Receipt for: $pkg</h2>"
778 pkg_info
779 echo "<a class='button green' href='?receipt=${pkg//+/%2B}'>receipt</a>"
780 . $wok/$pkg/receipt
782 ( cd $wok/$pkg; find stuff -type f 2> /dev/null ) | sort | \
783 while read file; do
784 echo "<a class='button' href='?stuff=${pkg//+/%2B}/${file//+/%2B}'>$file</a>"
785 done | sort
786 cat $wok/$pkg/receipt | show_code bash
787 ;;
789 files=*)
790 echo "<div id='content'>"
791 pkg=$(GET files)
792 dir=$(ls -d $WOK/$pkg/taz/$pkg-* 2>/dev/null)
793 size=$(du -hs $dir/fs | awk '{ print $1 }')
794 echo "<h2>Files installed by the package \"$pkg\" ($size)</h2>"
795 pkg_info
797 echo '<pre class="files">'
799 find $dir/fs -not -type d -print0 | sort -z | \
800 xargs -0 ls -ld --color=always | \
801 syntax_highlighter files | \
802 sed "s|\([^/]*\)/.*\(${dir#*wok}/fs\)\([^<]*\)\(<.*\)$|\1<a href=\"?download=../wok\2\3\">\3</a>\4|" |\
803 awk '
804 BEGIN { FS="\""; }
805 { gsub("+", "%2B", $2); print; }
806 '
808 echo '</pre>'
809 ;;
811 description=*)
812 echo "<div id='content'>"
813 pkg=$(GET description)
814 dir=$(ls -d $WOK/$pkg/taz/$pkg-* 2>/dev/null)
815 echo "<h2>Description of $pkg</h2>"
816 pkg_info
817 if [ -s "$dir/description.txt" ]; then
818 if [ -n "$md2html" ]; then
819 echo '<div id="content2">'
820 $md2html $dir/description.txt
821 echo '</div>'
822 else
823 cat $dir/description.txt | show_code markdown
824 fi
825 else
826 echo "<pre>No description of $pkg</pre>"
827 fi
828 ;;
830 man=*|doc=*|info=*)
831 echo '<div id="content">'
832 type=${QUERY_STRING%%=*}
833 pkg=$(GET $type)
834 dir=$WOK/$pkg/install/usr/share/$type
835 [ -d $dir ] || dir=$WOK/$pkg/install/usr/$type
836 [ -d $dir ] || dir=$(echo $WOK/$pkg/taz/*/fs/usr/share/$type)
837 [ -d $dir ] || dir=$(echo $WOK/$pkg/taz/*/fs/usr/$type)
838 page=$(GET file)
839 if [ -z "$page" ]; then
840 page=$(find $dir -type f | sed q)
841 page=${page#$dir/}
842 fi
844 echo "<h2>$(basename $page)</h2>"
846 pkg_info
847 echo '<div style="max-height: 5em; overflow: auto">'
848 find $dir -type f | sort | while read i ; do
849 [ -s $i ] || continue
850 case "$i" in
851 *.jp*g|*.png|*.gif|*.svg|*.css) continue
852 esac
853 i=${i#$dir/}
854 class=''; [ "$page" == "$i" ] && class=" plum"
855 case "$type" in
856 man)
857 man=$(basename $i .gz)
858 echo "<a class='button$class' href='?$type=$pkg&amp;file=$i'>${man%.*} (${man##*.})</a>"
859 ;;
860 info)
861 info=$(basename $i)
862 echo "<a class='button$class' href='?$type=$pkg&amp;file=$i#Top'>${info/.info/}</a>"
863 ;;
864 *)
865 echo "<a class='button$class' href='?$type=$pkg&amp;file=$i'>$(basename $i .gz)</a>"
866 ;;
867 esac
868 done
869 echo '</div>'
871 if [ -f "$dir/$page" ]; then
872 tmp="$(mktemp)"
873 docat "$dir/$page" > $tmp
874 [ -s "$tmp" ] &&
875 case "$type" in
876 info)
877 echo '<div id="content2" class="texinfo"><pre class="first">'
878 info2html < "$tmp"
879 echo '</pre></div>'
880 ;;
881 doc)
882 case "$page" in
883 *.sgml) class='xml';;
884 *.py) class='python';; # pycurl package
885 *) class='asciidoc';;
886 esac
887 case "$page" in
888 *.htm*)
889 echo '<div id="content2">'
890 cat
891 echo '</div>'
892 ;;
893 *)
894 show_code $class
895 ;;
896 esac < "$tmp"
897 ;;
898 man)
899 export TEXTDOMAIN='man2html'
900 echo "<div id='content2'>"
902 html=$(./man2html "$tmp" | sed -e '1,/<header>/d' \
903 -e 's|<a href="file:///[^>]*>\([^<]*\)</a>|\1|g' \
904 -e 's|<a href="?[1-9]\+[^>]*>\([^<]*\)</a>|\1|g')
906 if [ -n "$(echo "$html" | fgrep 'The requested file /tmp/tmp.')" ]; then
907 # Process the pre-formatted man-cat page
908 echo '<pre>'
909 sed '
910 s|M-bM-^@M-^S|—|g;
911 s|M-bM-^@M-^\\|<b>|g;
912 s|M-bM-^@M-^]|</b>|g
913 s|M-bM-^@M-^X|<u>|g;
914 s|M-bM-^@M-^Y|</u>|g;
915 s|M-BM-||g;
916 ' "$tmp"
917 echo '</pre>'
918 else
919 echo "$html"
920 fi
921 echo "</div>"
922 ;;
923 esac
924 rm -f $tmp
925 else
926 echo "<pre>File '$page' not exists!</pre>"
927 fi
928 ;;
930 *)
931 # We may have a toolchain.cgi script for cross cooker's
932 if [ -f "toolchain.cgi" ]; then
933 toolchain='toolchain.cgi'
934 else
935 toolchain='?pkg=slitaz-toolchain'
936 fi
937 # Main page with summary. Count only package include in ARCH,
938 # use 'cooker arch-db' to manually create arch.$ARCH files.
939 inwok=$(ls $WOK/*/arch.$ARCH | wc -l)
940 cooked=$(ls $PKGS/*.tazpkg | wc -l)
941 unbuilt=$(($inwok - $cooked))
942 pct=0
943 [ $inwok -gt 0 ] && pct=$(( ($cooked * 100) / $inwok ))
944 cat <<EOT
945 <div id="content2">
947 <form method="get" action="" class="r">
948 <input type="search" name="pkg" placeholder="Package" list="packages" autocorrect="off" autocapitalize="off"/>
949 </form>
951 <h2>Summary</h2>
953 <table>
954 <tr><td>Running command</td><td>: $(running_command)</td></tr>
955 <tr><td>Wok revision</td><td>: <a href="$WOK_URL">$(cat $wokrev)</a></td></tr>
956 <tr><td>Commits to cook</td><td>: $(wc -l < $commits)</td></tr>
957 <tr><td>Current cooklist</td><td>: $(wc -l < $cooklist)</td></tr>
958 <tr><td>Broken packages</td><td>: $(wc -l < $broken)</td></tr>
959 <tr><td>Blocked packages</td><td>: $(wc -l < $blocked)</td></tr>
960 <tr><td>Architecture</td><td>: $ARCH, <a href="$toolchain">toolchain</a></td></tr>
961 <tr><td>Server date</td><td>: $(date -u '+%F %R %Z')</td></tr>
963 </table>
964 EOT
966 [ -e $CACHE/cooker-request ] &&
967 [ $CACHE/activity -nt $CACHE/cooker-request ] &&
968 echo '<a class="button r" href="?poke">Poke cooker</a>'
970 cat <<EOT
971 <p class="info">Packages: $inwok in the wok · $cooked cooked · $unbuilt unbuilt</p>
973 <div class="pctbar">
974 <div class="pct" style="width: ${pct}%;">${pct}%</div>
975 </div>
977 <p>
978 Service logs:
979 <a href="?file=cookorder.log">cookorder</a> ·
980 <a href="?file=commits.log">commits</a> ·
981 <a href="?file=pkgdb.log">pkgdb</a><!-- ·
982 <a href="?file=installed.diff">installed.diff</a> -->
983 </p>
985 $(more_button activity "More activity" $CACHE/activity 12)
986 <h2 id="activity">Activity</h2>
988 <ul class="activity">
989 EOT
991 tac $CACHE/activity | head -n 12 | syntax_highlighter activity | \
992 sed 's|cooker.cgi||; s|^|<li>|; s|$|</li>|;'
994 echo '</ul>'
996 [ -s $cooknotes ] && cat <<EOT
997 $(more_button cooknotes "More notes" $cooknotes 12)
998 <h2 id="cooknotes">Cooknotes</h2>
999 <pre>
1000 $(tac $cooknotes | head -n 12 | syntax_highlighter activity)
1001 </pre>
1002 EOT
1004 [ -s $commits ] && cat <<EOT
1005 <h2 id="commits">Commits</h2>
1006 <ul class="activity">
1007 $(sed 's|^|<li>|; s|$|</li>|' $commits)
1008 </ul>
1009 EOT
1011 [ -s $cooklist ] && cat <<EOT
1012 $(more_button cooklist "Full cooklist" $cooklist 20)
1013 <h2 id="cooklist">Cooklist</h2>
1014 <ul class="activity">
1015 $(head -n 20 $cooklist | sed 's|^|<li>|; s|$|</li>|')
1016 </ul>
1017 EOT
1019 [ -s $broken ] && cat <<EOT
1020 $(more_button broken "All broken packages" $broken 20)
1021 <h2 id="broken">Broken</h2>
1022 <ul class="activity">
1023 $(head -n 20 $broken | sed "s#^[^']*#<a href='?pkg=\0'>\0</a>#g" | sed 's|^|<li>|; s|$|</li>|')
1024 </ul>
1025 EOT
1027 [ -s $blocked ] && cat <<EOT
1028 <h2 id="blocked">Blocked</h2>
1029 <ul class="activity">
1030 $(sed "s#^[^']*#<a href='?pkg=\0'>\0</a>#g" $blocked | sed 's|^|<li>|; s|$|</li>|')
1031 </ul>
1032 EOT
1034 cat <<EOT
1035 <h2 id="lastcook">Latest cook</h2>
1036 <ul class="activity">
1037 $(list_packages | sed 's|.tazpkg$||' | \
1038 sed "s|^.* :|<span class='log-date'>\0</span> <span style='white-space:nowrap'>|g; s|^|<li>|; s|$|</span></li>|")
1039 </ul>
1041 EOT
1042 datalist
1043 ;;
1044 esac
1047 page_footer
1048 exit 0