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

pkgs: fix export
author Christophe Lincoln <pankso@slitaz.org>
date Fri Apr 13 01:39:55 2012 +0200 (2012-04-13)
parents 4aca48ec3c57
children bc0ad61c35ad
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 if echo "$po" | fgrep -q "$lang"; then
92 break
93 fi
94 case "$lang" in
95 en) lang="C" ;;
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 zh) lang="zh_TW" ;;
103 esac
104 done
105 unset IFS
106 LANG=$lang
107 LC_ALL=$lang
108 export LANG LC_ALL
110 case "$OBJECT" in
111 File) selected_file="selected";;
112 Desc) selected_desc="selected";;
113 Tags) selected_tags="selected";;
114 Receipt) selected_receipt="selected";;
115 File_list) selected_file_list="selected";;
116 Depends) selected_depends="selected";;
117 BuildDepends) selected_build_depends="selected";;
118 FileOverlap) selected_overlap="selected";;
119 esac
121 case "$SLITAZ_VERSION" in
122 tiny) selected_tiny="selected";;
123 1.0) selected_1="selected";;
124 2.0) selected_2="selected";;
125 3.0) selected_3="selected";;
126 stable) selected_stable="selected";;
127 undigest) selected_undigest="selected";;
128 esac
130 # unescape query
131 SEARCH="$(echo $SEARCH | sed 's/%2B/+/g; s/%3A/:/g; s|%2F|/|g')"
133 WOK=/home/slitaz/$SLITAZ_VERSION/wok
134 PACKAGES_REPOSITORY=/home/slitaz/$SLITAZ_VERSION/packages
136 # --> header function from httphelper
137 echo "Content-type: text/html"
138 echo
140 # Search form
141 search_form()
142 {
144 cat << _EOT_
146 <div style="text-align: center; padding: 20px;">
147 <form method="get" action="$SCRIPT_NAME">
148 <input type="hidden" name="lang" value="$LANG" />
149 <select name="object">
150 <option value="Package">$(gettext "Package")</option>
151 <option $selected_desc value="Desc">$(gettext "Description")</option>
152 <option $selected_tags value="Tags">$(gettext "Tags")</option>
153 <option $selected_receipt value="Receipt">$(gettext "Receipt")</option>
154 <option $selected_depends value="Depends">$(gettext "Depends")</option>
155 <option $selected_build_depends value="BuildDepends">$(gettext "Build depends")</option>
156 <option $selected_file value="File">$(gettext "File")</option>
157 <option $selected_file_list value="File_list">$(gettext "File list")</option>
158 <option $selected_overlap value="FileOverlap">$(gettext "common files")</option>
159 </select>
160 <input type="text" name="query" size="20" value="$SEARCH" />
161 <select name="version">
162 <option value="cooking">$(gettext "cooking")</option>
163 <option $selected_stable value="stable">4.0</option>
164 <option $selected_3 value="3.0">3.0</option>
165 <option $selected_2 value="2.0">2.0</option>
166 <option $selected_1 value="1.0">1.0</option>
167 <option $selected_tiny value="tiny">$(gettext "tiny")</option>
168 <option $selected_undigest value="undigest">$(gettext "undigest")</option>
169 </select>
170 <input type="submit" value="$(gettext 'Search')" />
171 </form>
172 </div>
173 _EOT_
174 }
176 # xHTML5 Header.
177 xhtml_header() {
178 . lib/header.sh
179 }
181 # xHTML Footer.
182 xhtml_footer() {
183 PKGS=$(ls $WOK/ | wc -l)
184 FILES=$(unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | wc -l)
185 cat << _EOT_
187 <center>
188 <i>$(eval_ngettext "\$PKGS package" "\$PKGS packages" $PKGS)
189 $(eval_ngettext "and \$FILES file in \$SLITAZ_VERSION database" "and \$FILES files in \$SLITAZ_VERSION database" $FILES)</i>
190 </center>
192 <!-- End of content -->
193 </div>
195 <!-- Footer -->
196 <div id="footer">$(gettext "SliTaz Packages")</div>
198 </body>
199 </html>
200 _EOT_
201 }
203 installed_size()
204 {
205 [ $VERBOSE -gt 0 ] &&
206 grep -A 3 "^$1\$" $PACKAGES_REPOSITORY/packages.txt | \
207 grep installed | sed 's/.*(\(.*\) installed.*/(\1) /'
208 }
210 package_entry()
211 {
212 if [ -s "$(dirname $0)/$SLITAZ_VERSION/$CATEGORY.html" ]; then
213 cat << _EOT_
214 <a href="$SLITAZ_VERSION/$CATEGORY.html#$PACKAGE">$PACKAGE</a> $(installed_size $PACKAGE): $SHORT_DESC
215 _EOT_
216 else
217 PACKAGE_HREF="<u>$PACKAGE</u>"
218 PACKAGE_URL="http://mirror.slitaz.org/packages/$SLITAZ_VERSION/$PACKAGE-$VERSION$EXTRA_VERSION.tazpkg"
219 nslookup mirror.slitaz.org | grep -q 127.0.0.1 &&
220 PACKAGE_URL="http://mirror.slitaz.org/packages/$SLITAZ_VERSION/$(cd /var/www/slitaz/mirror/packages/$SLITAZ_VERSION ; ls $PACKAGE-$VERSION*.tazpkg)"
221 busybox wget -s $PACKAGE_URL 2> /dev/null &&
222 PACKAGE_HREF="<a href=\"$PACKAGE_URL\">$PACKAGE</a>"
223 cat << _EOT_
224 $PACKAGE_HREF $(installed_size $PACKAGE): $SHORT_DESC
225 _EOT_
226 fi
227 }
229 # Show loop in depends/build_depends chains
230 show_loops()
231 {
232 awk '
233 function chkloop(pkg, i, n)
234 {
235 if (n < 8)
236 for (i = 1; i <= split(deps[pkg],curdep," "); i++) {
237 if (curdep[i] == base || chkloop(curdep[i], 0, n+1)) {
238 split(deps[pkg],curdep," ")
239 p = curdep[i] " " p
240 return 1
241 }
242 }
243 return 0
244 }
245 {
246 for (i = 2; i <= NF; i++)
247 deps[$1] = deps[$1] " " $i
248 }
249 END {
250 for (pkg in deps) {
251 base = pkg
252 p = ""
253 if (chkloop(pkg, 0, 0))
254 print pkg " " p
255 #print pkg " : " p "..."
256 }
257 }' | while read line; do
258 set -- $line
259 case " $last " in
260 *\ $1\ *) continue
261 esac
262 last="$line"
263 pkg=$1
264 shift
265 echo $pkg ":" $@ "..."
266 done
267 }
269 # recursive dependencies scan
270 dep_scan()
271 {
272 for i in $1; do
273 case " $ALL_DEPS " in
274 *\ $i\ *) continue;;
275 esac
276 ALL_DEPS="$ALL_DEPS $i"
277 if [ -n "$2" ]; then
278 echo -n "$2"
279 (
280 . $WOK/$i/receipt
281 package_entry
282 )
283 fi
284 [ -f $WOK/$i/receipt ] || continue
285 DEPENDS=""
286 BUILD_DEPENDS=""
287 WANTED=""
288 . $WOK/$i/receipt
289 if [ -n "$3" ]; then
290 [ -n "$BUILD_DEPENDS$WANTED" ] &&
291 dep_scan "$WANTED $BUILD_DEPENDS" "$2 " $3
292 else
293 [ -n "$DEPENDS" ] && dep_scan "$DEPENDS" "$2 "
294 fi
295 done
296 }
298 # recursive reverse dependencies scan
299 rdep_scan()
300 {
301 SEARCH=$1
302 case "$SEARCH" in
303 glibc-base|gcc-lib-base)
304 $(gettext " glibc-base and gcc-lib-base are implicit dependencies,
305 <b>every</b> package is supposed to depend on them."); echo
306 return;;
307 esac
308 for i in $WOK/* ; do
309 DEPENDS=""
310 BUILD_DEPENDS=""
311 WANTED=""
312 . $i/receipt
313 if [ -n "$2" ]; then
314 echo "$(basename $i) $(echo $WANTED $BUILD_DEPENDS)"
315 else
316 echo "$(basename $i) $(echo $DEPENDS)"
317 fi
318 done | awk -v search=$SEARCH '
319 function show_deps(deps, all_deps, pkg, space)
320 {
321 if (all_deps[pkg] == 1) return
322 all_deps[pkg] = 1
323 if (space != "") printf "%s%s\n",space,pkg
324 for (i = 1; i <= split(deps[pkg], mydeps, " "); i++) {
325 show_deps(deps, all_deps, mydeps[i],"////" space)
326 }
327 }
329 {
330 all_deps[$1] = 0
331 for (i = 2; i <= NF; i++)
332 deps[$i] = deps[$i] " " $1
333 }
335 END {
336 show_deps(deps, all_deps, search, "")
337 }
338 ' | while read pkg; do
339 . $WOK/${pkg##*/}/receipt
340 cat << _EOT_
341 $(echo ${pkg%/*} | sed 's|/| |g') $(package_entry)
342 _EOT_
343 done
344 }
346 # Check package exists
347 package_exist()
348 {
349 [ -f $WOK/$1/receipt ] && return 0
350 cat << _EOT_
352 <h3>$(eval_gettext "No package \$SEARCH")</h3>
353 <pre>
354 _EOT_
355 return 1
356 }
358 # Display < > &
359 htmlize()
360 {
361 sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g'
362 }
364 echonb()
365 {
366 read n
367 echo -n "$n $1"
368 [ $n -gt 1 ] && echo -n s
369 }
371 display_packages_and_files()
372 {
373 last=""
374 while read pkg file; do
375 pkg=${pkg%:}
376 if [ "$pkg" != "$last" ]; then
377 . $WOK/$pkg/receipt
379 package_entry
380 last=$pkg
381 fi
382 echo " $file"
383 done
384 }
386 #
387 # Handle GET requests
388 #
389 case " $(GET) " in
390 *\ debug\ *)
391 xhtml_header
392 echo "<h2>Debug info</h2>"
393 echo "<p>Auto detected language: LANG=$LANG (lang=$lang)</p>"
394 echo '<pre>'
395 httpinfo
396 echo '</pre>'
397 xhtml_footer
398 exit 0 ;;
399 esac
401 # Display search form and result if requested.
402 if [ "$REQUEST_METHOD" != "POST" ]; then
403 xhtml_header
404 echo "<h2>$(gettext "Search for packages")</h2>"
405 search_form
406 xhtml_footer
407 else
408 xhtml_header
409 echo "$(gettext "Search for packages")</h2>"
410 search_form
411 if [ "$OBJECT" = "Depends" ]; then
412 if [ -z "$SEARCH" ]; then
413 cat << _EOT_
415 <h3>$(gettext "Depends loops")</h3>
416 <pre>
417 _EOT_
418 for i in $WOK/*/receipt; do
419 PACKAGE=
420 DEPENDS=
421 . $i
422 echo "$PACKAGE $(echo $DEPENDS)"
423 done | show_loops
424 cat << _EOT_
425 </pre>
426 _EOT_
427 elif package_exist $SEARCH ; then
428 cat << _EOT_
430 <h3>$(eval_gettext "Dependency tree for: \$SEARCH")</h3>
431 <pre>
432 _EOT_
433 ALL_DEPS=""
434 dep_scan $SEARCH ""
435 SUGGESTED=""
436 . $WOK/$SEARCH/receipt
437 if [ -n "$SUGGESTED" ]; then
438 cat << _EOT_
439 </pre>
441 <h3>$(eval_gettext "Dependency tree for: \$SEARCH (SUGGESTED)")</h3>
442 <pre>
443 _EOT_
444 ALL_DEPS=""
445 dep_scan "$SUGGESTED" " "
446 fi
447 cat << _EOT_
448 </pre>
450 <h3>$(eval_gettext "Reverse dependency tree for: \$SEARCH")</h3>
451 <pre>
452 _EOT_
453 ALL_DEPS=""
454 rdep_scan $SEARCH
455 cat << _EOT_
456 </pre>
457 _EOT_
458 fi
459 elif [ "$OBJECT" = "BuildDepends" ]; then
460 if [ -z "$SEARCH" ]; then
461 cat << _EOT_
463 <h3>$(gettext "Build depends loops")</h3>
464 <pre>
465 _EOT_
466 for i in $WOK/*/receipt; do
467 PACKAGE=
468 WANTED=
469 BUILD_DEPENDS=
470 . $i
471 echo "$PACKAGE $WANTED $(echo $BUILD_DEPENDS)"
472 done | show_loops
473 cat << _EOT_
474 </pre>
475 _EOT_
476 elif package_exist $SEARCH ; then
477 cat << _EOT_
479 <h3>$(eval_gettext "\$SEARCH needs these packages to be built")</h3>
480 <pre>
481 _EOT_
482 ALL_DEPS=""
483 dep_scan $SEARCH "" build
484 cat << _EOT_
485 </pre>
487 <h3>$(eval_gettext "Packages who need \$SEARCH to be built")</h3>
488 <pre>
489 _EOT_
490 ALL_DEPS=""
491 rdep_scan $SEARCH build
492 cat << _EOT_
493 </pre>
494 _EOT_
495 fi
496 elif [ "$OBJECT" = "FileOverlap" ]; then
497 if package_exist $SEARCH ; then
498 cat << _EOT_
500 <h3>$(eval_gettext "These packages may overload files of \$SEARCH")</h3>
501 <pre>
502 _EOT_
503 ( unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | grep ^$SEARCH: ;
504 unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | grep -v ^$SEARCH: ) | awk '
505 BEGIN { pkg=""; last="x" }
506 {
507 if ($2 == "") next
508 if (index($2,last) == 1 && substr($2,1+length(last),1) == "/")
509 delete file[last]
510 last=$2
511 if (pkg == "") pkg=$1
512 if ($1 == pkg) file[$2]=$1
513 else if (file[$2] == pkg) print
514 }
515 ' | display_packages_and_files
516 cat << _EOT_
517 </pre>
518 _EOT_
519 fi
520 elif [ "$OBJECT" = "File" ]; then
521 cat << _EOT_
523 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
524 <pre>
525 _EOT_
526 last=""
527 unlzma -c $PACKAGES_REPOSITORY/files.list.lzma \
528 | grep "$SEARCH" | while read pkg file; do
529 echo "$file" | grep -q "$SEARCH" || continue
530 if [ "$last" != "${pkg%:}" ]; then
531 last=${pkg%:}
532 (
533 . $WOK/$last/receipt
534 cat << _EOT_
536 <i>$(package_entry)</i>
537 _EOT_
538 )
539 fi
540 echo " $file"
541 done
542 elif [ "$OBJECT" = "File_list" ]; then
543 if package_exist $SEARCH; then
544 cat << _EOT_
546 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
547 <pre>
548 _EOT_
549 last=""
550 unlzma -c $PACKAGES_REPOSITORY/files.list.lzma \
551 | grep ^$SEARCH: | sed 's/.*: / /' | sort
552 cat << _EOT_
553 </pre>
554 <pre>
555 $(unlzma -c $PACKAGES_REPOSITORY/files.list.lzma | grep ^$SEARCH: | wc -l | echonb file) \
556 $(busybox sed -n "/^$SEARCH$/{nnnpq}" $PACKAGES_REPOSITORY/packages.txt)
557 _EOT_
558 fi
559 elif [ "$OBJECT" = "Desc" ]; then
560 if [ -f $WOK/$SEARCH/description.txt ]; then
561 cat << _EOT_
563 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
564 <pre>
565 $(htmlize < $WOK/$SEARCH/description.txt)
566 </pre>
567 _EOT_
568 else
569 cat << _EOT_
571 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
572 <pre>
573 _EOT_
574 last=""
575 grep -i "$SEARCH" $PACKAGES_REPOSITORY/packages.desc | \
576 sort | while read pkg extras ; do
577 . $WOK/$pkg/receipt
578 package_entry
579 done
580 fi
581 elif [ "$OBJECT" = "Tags" ]; then
582 cat << _EOT_
584 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
585 <pre>
586 _EOT_
587 last=""
588 grep ^TAGS= $WOK/*/receipt | grep -i "$SEARCH" | \
589 sed "s|$WOK/\(.*\)/receipt:.*|\1|" | sort | while read pkg ; do
590 . $WOK/$pkg/receipt
591 package_entry
592 done
593 elif [ "$OBJECT" = "Receipt" ]; then
594 package_exist $SEARCH && cat << _EOT_
596 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
597 <pre>
598 $(if [ -f $WOK/$SEARCH/taz/*/receipt ]; then
599 cat $WOK/$SEARCH/taz/*/receipt
600 else
601 cat $WOK/$SEARCH/receipt
602 fi | htmlize)
603 </pre>
604 _EOT_
605 else
606 cat << _EOT_
608 <h3>$(eval_gettext "Result for: \$SEARCH")</h3>
609 <pre>
610 _EOT_
611 for pkg in `ls $WOK/ | grep "$SEARCH"`
612 do
613 . $WOK/$pkg/receipt
614 DESC=" <a href=\"?desc=$pkg\">$(gettext description)</a>"
615 [ -f $WOK/$pkg/description.txt ] || DESC=""
616 cat << _EOT_
617 $(package_entry)$DESC
618 _EOT_
619 done
620 equiv=$PACKAGES_REPOSITORY/packages.equiv
621 vpkgs="$(cat $equiv | cut -d= -f1 | grep $SEARCH)"
622 for vpkg in $vpkgs ; do
623 cat << _EOT_
624 </pre>
626 <h3>$(eval_gettext "Result for: \$SEARCH (package providing \$vpkg)")</h3>
627 <pre>
628 _EOT_
629 for pkg in $(grep $vpkg= $equiv | sed "s/$vpkg=//"); do
630 . $WOK/${pkg#*:}/receipt
631 package_entry
632 done
633 done
634 fi
635 cat << _EOT_
636 </pre>
637 _EOT_
638 xhtml_footer
639 fi
641 exit 0