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

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