slitaz-forge view pkgs/search.sh @ rev 278

pkgs: use LANG directly and so we keep $lang
author Christophe Lincoln <pankso@slitaz.org>
date Fri Apr 13 01:53:02 2012 +0200 (2012-04-13)
parents bc0ad61c35ad
children c0e954250657
line source
1 #!/bin/sh
2 # Tiny CGI search engine for SliTaz packages on http://pkgs.slitaz.org/
3 # Christophe Lincoln <pankso@slitaz.org>
4 # Aleksej Bobylev <al.bobylev@gmail.com> - i18n
5 #
6 . /usr/lib/slitaz/httphelper.sh
8 # This can be removed when we use $(GET var) PHP a like syntaxe from
9 # httphelper.sh
10 read QUERY_STRING
11 for i in $(echo $QUERY_STRING | sed 's/&/ /g'); do
12 i=$(httpd -d $i)
13 eval $i
14 done
15 LANG=$lang
16 SEARCH=$query
17 SLITAZ_VERSION=$version
18 OBJECT=$object
19 DATE=$(date +%Y-%m-%d\ %H:%M:%S)
20 VERSION=cooking
21 SCRIPT_NAME="search.sh"
23 # Internal variables
24 po="de fr pt ru zh"
26 # Internationalization
27 . /usr/bin/gettext.sh
28 TEXTDOMAIN='tazpkg-web'
29 export TEXTDOMAIN
31 if [ "$REQUEST_METHOD" = "GET" ]; then
32 SEARCH=""
33 VERBOSE=0
34 for i in $(echo $REQUEST_URI | sed 's/[?&]/ /g'); do
35 # i=$(httpd -d $i)
36 SLITAZ_VERSION=cooking
37 case "$(echo $i | tr [A-Z] [a-z])" in
38 query=*|search=*)
39 [ ${i#*=} == Search ] || SEARCH=${i#*=};;
40 object=*)
41 OBJECT=${i#*=};;
42 verbose=*)
43 VERBOSE=${i#*=};;
44 lang=*)
45 LANG=${i#*=};;
46 file=*)
47 SEARCH=${i#*=}
48 OBJECT=File;;
49 desc=*)
50 SEARCH=${i#*=}
51 OBJECT=Desc;;
52 tags=*)
53 SEARCH=${i#*=}
54 OBJECT=Tags;;
55 receipt=*)
56 SEARCH=${i#*=}
57 OBJECT=Receipt;;
58 filelist=*)
59 SEARCH=${i#*=}
60 OBJECT=File_list;;
61 package=*)
62 SEARCH=${i#*=}
63 OBJECT=Package;;
64 depends=*)
65 SEARCH=${i#*=}
66 OBJECT=Depends;;
67 builddepends=*)
68 SEARCH=${i#*=}
69 OBJECT=BuildDepends;;
70 fileoverlap=*)
71 SEARCH=${i#*=}
72 OBJECT=FileOverlap;;
73 version=s*|version=3*)
74 SLITAZ_VERSION=stable;;
75 version=[1-9]*)
76 i=${i%%.*}
77 SLITAZ_VERSION=${i#*=}.0;;
78 version=u*)
79 SLITAZ_VERSION=undigest;;
80 esac
81 done
82 [ -n "$SEARCH" ] && REQUEST_METHOD="POST"
83 [ "$SEARCH" == "." ] && SEARCH=
84 fi
86 # Content negotiation for Gettext
87 IFS=","
88 for lang in $HTTP_ACCEPT_LANGUAGE
89 do
90 lang=${lang%;*} lang=${lang# } lang=${lang%-*}
91 case "$lang" in
92 en) LANG="C" ;;
93 de) LANG="de_DE" ;;
94 es) LANG="es_ES" ;;
95 fr) LANG="fr_FR" ;;
96 it) LANG="it_IT" ;;
97 pt) LANG="pt_BR" ;;
98 ru) LANG="ru_RU" ;;
99 zh) LANG="zh_TW" ;;
100 esac
101 if echo "$po" | fgrep -q "$lang"; then
102 break
103 fi
104 done
105 unset IFS
106 export LANG LC_ALL=$LANG
108 case "$OBJECT" in
109 File) selected_file="selected";;
110 Desc) selected_desc="selected";;
111 Tags) selected_tags="selected";;
112 Receipt) selected_receipt="selected";;
113 File_list) selected_file_list="selected";;
114 Depends) selected_depends="selected";;
115 BuildDepends) selected_build_depends="selected";;
116 FileOverlap) selected_overlap="selected";;
117 esac
119 case "$SLITAZ_VERSION" in
120 tiny) selected_tiny="selected";;
121 1.0) selected_1="selected";;
122 2.0) selected_2="selected";;
123 3.0) selected_3="selected";;
124 stable) selected_stable="selected";;
125 undigest) selected_undigest="selected";;
126 esac
128 # unescape query
129 SEARCH="$(echo $SEARCH | sed 's/%2B/+/g; s/%3A/:/g; s|%2F|/|g')"
131 WOK=/home/slitaz/$SLITAZ_VERSION/wok
132 PACKAGES_REPOSITORY=/home/slitaz/$SLITAZ_VERSION/packages
134 # --> header function from httphelper
135 echo "Content-type: text/html"
136 echo
138 # Search form
139 search_form()
140 {
141 cat << _EOT_
143 <div style="text-align: center; padding: 20px;">
144 <form method="get" action="$SCRIPT_NAME">
145 <input type="hidden" name="lang" value="$LANG" />
146 <select name="object">
147 <option value="Package">$(gettext "Package")</option>
148 <option $selected_desc value="Desc">$(gettext "Description")</option>
149 <option $selected_tags value="Tags">$(gettext "Tags")</option>
150 <option $selected_receipt value="Receipt">$(gettext "Receipt")</option>
151 <option $selected_depends value="Depends">$(gettext "Depends")</option>
152 <option $selected_build_depends value="BuildDepends">$(gettext "Build depends")</option>
153 <option $selected_file value="File">$(gettext "File")</option>
154 <option $selected_file_list value="File_list">$(gettext "File list")</option>
155 <option $selected_overlap value="FileOverlap">$(gettext "common files")</option>
156 </select>
157 <input type="text" name="query" size="20" value="$SEARCH" />
158 <select name="version">
159 <option value="cooking">$(gettext "cooking")</option>
160 <option $selected_stable value="stable">4.0</option>
161 <option $selected_3 value="3.0">3.0</option>
162 <option $selected_2 value="2.0">2.0</option>
163 <option $selected_1 value="1.0">1.0</option>
164 <option $selected_tiny value="tiny">$(gettext "tiny")</option>
165 <option $selected_undigest value="undigest">$(gettext "undigest")</option>
166 </select>
167 <input type="submit" value="$(gettext 'Search')" />
168 </form>
169 </div>
170 _EOT_
171 }
173 # xHTML5 Header.
174 xhtml_header() {
175 . lib/header.sh
176 }
178 # xHTML Footer.
179 xhtml_footer() {
180 PKGS=$(ls $WOK/ | wc -l)
181 FILES=$(unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | wc -l)
182 cat << _EOT_
184 <center>
185 <i>$(eval_ngettext "\$PKGS package" "\$PKGS packages" $PKGS)
186 $(eval_ngettext "and \$FILES file in \$SLITAZ_VERSION database" "and \$FILES files in \$SLITAZ_VERSION database" $FILES)</i>
187 </center>
189 <!-- End of content -->
190 </div>
192 <!-- Footer -->
193 <div id="footer">$(gettext "SliTaz Packages")</div>
195 </body>
196 </html>
197 _EOT_
198 }
200 installed_size()
201 {
202 [ $VERBOSE -gt 0 ] &&
203 grep -A 3 "^$1\$" $PACKAGES_REPOSITORY/packages.txt | \
204 grep installed | sed 's/.*(\(.*\) installed.*/(\1) /'
205 }
207 package_entry()
208 {
209 if [ -s "$(dirname $0)/$SLITAZ_VERSION/$CATEGORY.html" ]; then
210 cat << _EOT_
211 <a href="$SLITAZ_VERSION/$CATEGORY.html#$PACKAGE">$PACKAGE</a> $(installed_size $PACKAGE): $SHORT_DESC
212 _EOT_
213 else
214 PACKAGE_HREF="<u>$PACKAGE</u>"
215 PACKAGE_URL="http://mirror.slitaz.org/packages/$SLITAZ_VERSION/$PACKAGE-$VERSION$EXTRA_VERSION.tazpkg"
216 nslookup mirror.slitaz.org | grep -q 127.0.0.1 &&
217 PACKAGE_URL="http://mirror.slitaz.org/packages/$SLITAZ_VERSION/$(cd /var/www/slitaz/mirror/packages/$SLITAZ_VERSION ; ls $PACKAGE-$VERSION*.tazpkg)"
218 busybox wget -s $PACKAGE_URL 2> /dev/null &&
219 PACKAGE_HREF="<a href=\"$PACKAGE_URL\">$PACKAGE</a>"
220 cat << _EOT_
221 $PACKAGE_HREF $(installed_size $PACKAGE): $SHORT_DESC
222 _EOT_
223 fi
224 }
226 # Show loop in depends/build_depends chains
227 show_loops()
228 {
229 awk '
230 function chkloop(pkg, i, n)
231 {
232 if (n < 8)
233 for (i = 1; i <= split(deps[pkg],curdep," "); i++) {
234 if (curdep[i] == base || chkloop(curdep[i], 0, n+1)) {
235 split(deps[pkg],curdep," ")
236 p = curdep[i] " " p
237 return 1
238 }
239 }
240 return 0
241 }
242 {
243 for (i = 2; i <= NF; i++)
244 deps[$1] = deps[$1] " " $i
245 }
246 END {
247 for (pkg in deps) {
248 base = pkg
249 p = ""
250 if (chkloop(pkg, 0, 0))
251 print pkg " " p
252 #print pkg " : " p "..."
253 }
254 }' | while read line; do
255 set -- $line
256 case " $last " in
257 *\ $1\ *) continue
258 esac
259 last="$line"
260 pkg=$1
261 shift
262 echo $pkg ":" $@ "..."
263 done
264 }
266 # recursive dependencies scan
267 dep_scan()
268 {
269 for i in $1; do
270 case " $ALL_DEPS " in
271 *\ $i\ *) continue;;
272 esac
273 ALL_DEPS="$ALL_DEPS $i"
274 if [ -n "$2" ]; then
275 echo -n "$2"
276 (
277 . $WOK/$i/receipt
278 package_entry
279 )
280 fi
281 [ -f $WOK/$i/receipt ] || continue
282 DEPENDS=""
283 BUILD_DEPENDS=""
284 WANTED=""
285 . $WOK/$i/receipt
286 if [ -n "$3" ]; then
287 [ -n "$BUILD_DEPENDS$WANTED" ] &&
288 dep_scan "$WANTED $BUILD_DEPENDS" "$2 " $3
289 else
290 [ -n "$DEPENDS" ] && dep_scan "$DEPENDS" "$2 "
291 fi
292 done
293 }
295 # recursive reverse dependencies scan
296 rdep_scan()
297 {
298 SEARCH=$1
299 case "$SEARCH" in
300 glibc-base|gcc-lib-base)
301 $(gettext " glibc-base and gcc-lib-base are implicit dependencies,
302 <b>every</b> package is supposed to depend on them."); echo
303 return;;
304 esac
305 for i in $WOK/* ; do
306 DEPENDS=""
307 BUILD_DEPENDS=""
308 WANTED=""
309 . $i/receipt
310 if [ -n "$2" ]; then
311 echo "$(basename $i) $(echo $WANTED $BUILD_DEPENDS)"
312 else
313 echo "$(basename $i) $(echo $DEPENDS)"
314 fi
315 done | awk -v search=$SEARCH '
316 function show_deps(deps, all_deps, pkg, space)
317 {
318 if (all_deps[pkg] == 1) return
319 all_deps[pkg] = 1
320 if (space != "") printf "%s%s\n",space,pkg
321 for (i = 1; i <= split(deps[pkg], mydeps, " "); i++) {
322 show_deps(deps, all_deps, mydeps[i],"////" space)
323 }
324 }
326 {
327 all_deps[$1] = 0
328 for (i = 2; i <= NF; i++)
329 deps[$i] = deps[$i] " " $1
330 }
332 END {
333 show_deps(deps, all_deps, search, "")
334 }
335 ' | while read pkg; do
336 . $WOK/${pkg##*/}/receipt
337 cat << _EOT_
338 $(echo ${pkg%/*} | sed 's|/| |g') $(package_entry)
339 _EOT_
340 done
341 }
343 # Check package exists
344 package_exist()
345 {
346 [ -f $WOK/$1/receipt ] && return 0
347 cat << _EOT_
349 <h3>$(eval_gettext "No package \$SEARCH")</h3>
350 <pre>
351 _EOT_
352 return 1
353 }
355 # Display < > &
356 htmlize()
357 {
358 sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g'
359 }
361 echonb()
362 {
363 read n
364 echo -n "$n $1"
365 [ $n -gt 1 ] && echo -n s
366 }
368 display_packages_and_files()
369 {
370 last=""
371 while read pkg file; do
372 pkg=${pkg%:}
373 if [ "$pkg" != "$last" ]; then
374 . $WOK/$pkg/receipt
376 package_entry
377 last=$pkg
378 fi
379 echo " $file"
380 done
381 }
383 #
384 # Handle GET requests
385 #
386 case " $(GET) " in
387 *\ debug\ *)
388 xhtml_header
389 echo "<h2>Debug info</h2>"
390 echo "<p>Auto detected language: LANG=$LANG (lang=$lang)</p>"
391 echo '<pre>'
392 httpinfo
393 echo '</pre>'
394 xhtml_footer
395 exit 0 ;;
396 esac
398 # Display search form and result if requested.
399 if [ "$REQUEST_METHOD" != "POST" ]; then
400 xhtml_header
401 echo "<h2>$(gettext "Search for packages")</h2>"
402 search_form
403 xhtml_footer
404 else
405 xhtml_header
406 echo "$(gettext "Search for packages")</h2>"
407 search_form
408 if [ "$OBJECT" = "Depends" ]; then
409 if [ -z "$SEARCH" ]; then
410 cat << _EOT_
412 <h3>$(gettext "Depends loops")</h3>
413 <pre>
414 _EOT_
415 for i in $WOK/*/receipt; do
416 PACKAGE=
417 DEPENDS=
418 . $i
419 echo "$PACKAGE $(echo $DEPENDS)"
420 done | show_loops
421 cat << _EOT_
422 </pre>
423 _EOT_
424 elif package_exist $SEARCH ; then
425 cat << _EOT_
427 <h3>$(eval_gettext "Dependency tree for: \$SEARCH")</h3>
428 <pre>
429 _EOT_
430 ALL_DEPS=""
431 dep_scan $SEARCH ""
432 SUGGESTED=""
433 . $WOK/$SEARCH/receipt
434 if [ -n "$SUGGESTED" ]; then
435 cat << _EOT_
436 </pre>
438 <h3>$(eval_gettext "Dependency tree for: \$SEARCH (SUGGESTED)")</h3>
439 <pre>
440 _EOT_
441 ALL_DEPS=""
442 dep_scan "$SUGGESTED" " "
443 fi
444 cat << _EOT_
445 </pre>
447 <h3>$(eval_gettext "Reverse dependency tree for: \$SEARCH")</h3>
448 <pre>
449 _EOT_
450 ALL_DEPS=""
451 rdep_scan $SEARCH
452 cat << _EOT_
453 </pre>
454 _EOT_
455 fi
456 elif [ "$OBJECT" = "BuildDepends" ]; then
457 if [ -z "$SEARCH" ]; then
458 cat << _EOT_
460 <h3>$(gettext "Build depends loops")</h3>
461 <pre>
462 _EOT_
463 for i in $WOK/*/receipt; do
464 PACKAGE=
465 WANTED=
466 BUILD_DEPENDS=
467 . $i
468 echo "$PACKAGE $WANTED $(echo $BUILD_DEPENDS)"
469 done | show_loops
470 cat << _EOT_
471 </pre>
472 _EOT_
473 elif package_exist $SEARCH ; then
474 cat << _EOT_
476 <h3>$(eval_gettext "\$SEARCH needs these packages to be built")</h3>
477 <pre>
478 _EOT_
479 ALL_DEPS=""
480 dep_scan $SEARCH "" build
481 cat << _EOT_
482 </pre>
484 <h3>$(eval_gettext "Packages who need \$SEARCH to be built")</h3>
485 <pre>
486 _EOT_
487 ALL_DEPS=""
488 rdep_scan $SEARCH build
489 cat << _EOT_
490 </pre>
491 _EOT_
492 fi
493 elif [ "$OBJECT" = "FileOverlap" ]; then
494 if package_exist $SEARCH ; then
495 cat << _EOT_
497 <h3>$(eval_gettext "These packages may overload files of \$SEARCH")</h3>
498 <pre>
499 _EOT_
500 ( unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | grep ^$SEARCH: ;
501 unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | grep -v ^$SEARCH: ) | awk '
502 BEGIN { pkg=""; last="x" }
503 {
504 if ($2 == "") next
505 if (index($2,last) == 1 && substr($2,1+length(last),1) == "/")
506 delete file[last]
507 last=$2
508 if (pkg == "") pkg=$1
509 if ($1 == pkg) file[$2]=$1
510 else if (file[$2] == pkg) print
511 }
512 ' | display_packages_and_files
513 cat << _EOT_
514 </pre>
515 _EOT_
516 fi
517 elif [ "$OBJECT" = "File" ]; then
518 cat << _EOT_
520 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
521 <pre>
522 _EOT_
523 last=""
524 unlzma -c $PACKAGES_REPOSITORY/files.list.lzma \
525 | grep "$SEARCH" | while read pkg file; do
526 echo "$file" | grep -q "$SEARCH" || continue
527 if [ "$last" != "${pkg%:}" ]; then
528 last=${pkg%:}
529 (
530 . $WOK/$last/receipt
531 cat << _EOT_
533 <i>$(package_entry)</i>
534 _EOT_
535 )
536 fi
537 echo " $file"
538 done
539 elif [ "$OBJECT" = "File_list" ]; then
540 if package_exist $SEARCH; then
541 cat << _EOT_
543 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
544 <pre>
545 _EOT_
546 last=""
547 unlzma -c $PACKAGES_REPOSITORY/files.list.lzma \
548 | grep ^$SEARCH: | sed 's/.*: / /' | sort
549 cat << _EOT_
550 </pre>
551 <pre>
552 $(unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | grep ^$SEARCH: | wc -l | echonb file) \
553 $(busybox sed -n "/^$SEARCH$/{nnnpq}" $PACKAGES_REPOSITORY/packages.txt)
554 _EOT_
555 fi
556 elif [ "$OBJECT" = "Desc" ]; then
557 if [ -f $WOK/$SEARCH/description.txt ]; then
558 cat << _EOT_
560 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
561 <pre>
562 $(htmlize < $WOK/$SEARCH/description.txt)
563 </pre>
564 _EOT_
565 else
566 cat << _EOT_
568 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
569 <pre>
570 _EOT_
571 last=""
572 grep -i "$SEARCH" $PACKAGES_REPOSITORY/packages.desc | \
573 sort | while read pkg extras ; do
574 . $WOK/$pkg/receipt
575 package_entry
576 done
577 fi
578 elif [ "$OBJECT" = "Tags" ]; then
579 cat << _EOT_
581 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
582 <pre>
583 _EOT_
584 last=""
585 grep ^TAGS= $WOK/*/receipt | grep -i "$SEARCH" | \
586 sed "s|$WOK/\(.*\)/receipt:.*|\1|" | sort | while read pkg ; do
587 . $WOK/$pkg/receipt
588 package_entry
589 done
590 elif [ "$OBJECT" = "Receipt" ]; then
591 package_exist $SEARCH && cat << _EOT_
593 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
594 <pre>
595 $(if [ -f $WOK/$SEARCH/taz/*/receipt ]; then
596 cat $WOK/$SEARCH/taz/*/receipt
597 else
598 cat $WOK/$SEARCH/receipt
599 fi | htmlize)
600 </pre>
601 _EOT_
602 else
603 cat << _EOT_
605 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
606 <pre>
607 _EOT_
608 for pkg in `ls $WOK/ | grep "$SEARCH"`
609 do
610 . $WOK/$pkg/receipt
611 DESC=" <a href=\"?desc=$pkg\">$(gettext description)</a>"
612 [ -f $WOK/$pkg/description.txt ] || DESC=""
613 cat << _EOT_
614 $(package_entry)$DESC
615 _EOT_
616 done
617 equiv=$PACKAGES_REPOSITORY/packages.equiv
618 vpkgs="$(cat $equiv | cut -d= -f1 | grep $SEARCH)"
619 for vpkg in $vpkgs ; do
620 cat << _EOT_
621 </pre>
623 <h3>$(eval_gettext "Result for: \$SEARCH (package providing \$vpkg)")</h3>
624 <pre>
625 _EOT_
626 for pkg in $(grep $vpkg= $equiv | sed "s/$vpkg=//"); do
627 . $WOK/${pkg#*:}/receipt
628 package_entry
629 done
630 done
631 fi
632 cat << _EOT_
633 </pre>
634 _EOT_
635 xhtml_footer
636 fi
638 exit 0