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

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