tazbug view web/bugs.cgi @ rev 31

check i18n: make {pot,msgfmt,clean}; fix Makefile; change i18n; add ru.po
author Aleksej Bobylev <al.bobylev@gmail.com>
date Sun Jul 01 22:26:53 2012 +0000 (2012-07-01)
parents ea58d117d71a
children db97998089d6
line source
1 #!/bin/sh
2 #
3 # TazBug Web interface
4 #
5 # Copyright (C) 2012 SliTaz GNU/Linux - BSD License
6 #
7 . /usr/lib/slitaz/httphelper
8 [ -f "/etc/slitaz/tazbug.conf" ] && . /etc/slitaz/tazbug.conf
9 [ -f "../tazbug.conf" ] && . ../tazbug.conf
11 # Internal variable
12 bugdir="bug"
13 plugins="plugins"
14 sessions="/tmp/tazbug/sessions"
15 po=""
17 # Content negotiation for Gettext
18 IFS=","
19 for lang in $HTTP_ACCEPT_LANGUAGE
20 do
21 lang=${lang%;*} lang=${lang# } lang=${lang%-*}
22 case "$lang" in
23 en) LANG="C" ;;
24 de) LANG="de_DE" ;;
25 es) LANG="es_ES" ;;
26 fr) LANG="fr_FR" ;;
27 it) LANG="it_IT" ;;
28 pt) LANG="pt_BR" ;;
29 ru) LANG="ru_RU" ;;
30 zh) LANG="zh_TW" ;;
31 esac
32 if echo "$po" | fgrep -q "$lang"; then
33 break
34 fi
35 done
36 unset IFS
37 export LANG LC_ALL=$LANG
39 # Internationalization: $(gettext "")
40 . /usr/bin/gettext.sh
41 TEXTDOMAIN='tazbug'
42 export TEXTDOMAIN
44 #
45 # Functions
46 #
48 # HTML 5 header.
49 html_header() {
50 cat lib/header.html
51 }
53 # HTML 5 footer.
54 html_footer() {
55 cat << EOT
56 </div>
58 <div id="footer">
59 <a href="./">SliTaz Bugs</a> -
60 <a href="./?README">README</a>
61 </div>
63 </body>
64 </html>
65 EOT
66 }
68 # Check if user is auth
69 check_auth() {
70 auth="$(COOKIE auth)"
71 user="$(echo $auth | cut -d ":" -f 1)"
72 md5cookie="$(echo $auth | cut -d ":" -f 2)"
73 [ -f "$sessions/$user" ] && md5session="$(cat $sessions/$user)"
74 if [ "$md5cookie" == "$md5session" ] && [ "$auth" ]; then
75 return 0
76 else
77 return 1
78 fi
79 }
81 # Authentified or not
82 user_box() {
83 if check_auth; then
84 . $PEOPLE/$user/account.conf
85 cat << EOT
86 <div id="user">
87 <a href="?user=$user">$(get_gravatar $MAIL 20)</a>
88 <a href="?logout">$(gettext 'Log out')</a>
89 </div>
90 EOT
91 else
92 cat << EOT
93 <div id="user">
94 <a href="?login"><img src="images/avatar.png" alt="[ User ]" /></a>
95 <a href="?login">$(gettext 'Log in')</a>
96 </div>
97 EOT
98 fi
99 cat << EOT
101 <div id="search">
102 <form method="get" action="./">
103 <input type="text" name="search" placeholder="$(gettext 'Search')" />
104 <!-- <input type="submit" value="$(gettext 'Search')" /> -->
105 </form>
106 </div>
108 <!-- Content -->
109 <div id="content">
111 EOT
112 }
114 # Login page
115 login_page() {
116 cat << EOT
117 <h2>$(gettext 'Login')</h2>
119 <div id="account-info">
120 <p>$(gettext "No account yet? Please signup using the SliTaz Bugs reporter \
121 on your SliTaz system.")</p>
122 <p>$(gettext "Tip: to attach big files or images, you can use SliTaz Paste \
123 services:") <a href="http://paste.slitaz.org/">paste.slitaz.org</a></p>
124 </div>
126 <div id="login">
127 <form method="post" action="$SCRIPT_NAME">
128 <input type="text" name="auth" placeholder="$(gettext 'User name')" />
129 <input type="password" name="pass" placeholder="$(gettext 'Password')" />
130 <div>
131 <input type="submit" value="$(gettext 'Log in')" />
132 $error
133 </div>
134 </form>
135 </div>
137 <div style="clear: both;"></div>
138 EOT
139 }
141 # Display user public profile.
142 public_people() {
143 cat << EOT
144 <pre>
145 $(eval_gettext 'Real name : $NAME')
146 </pre>
147 EOT
148 }
150 # Display authentified user profile. TODO: change password
151 auth_people() {
152 cat << EOT
153 <pre>
154 $(eval_gettext 'Real name : $NAME')
155 $(eval_gettext 'Email : $MAIL')
156 $(eval_gettext 'Secure key : $KEY')
157 </pre>
158 EOT
159 }
161 # Usage: list_bugs STATUS
162 list_bugs() {
163 bug="$1"
164 echo "<h3>$(eval_gettext '$bug Bug')</h3>"
165 for pr in critical standard
166 do
167 for bug in $(fgrep -H "$1" $bugdir/*/bug.conf | cut -d ":" -f 1)
168 do
169 . $bug
170 id=$(dirname $bug | cut -d "/" -f 2)
171 if [ "$PRIORITY" == "$pr" ]; then
172 cat << EOT
173 <pre>
174 $(gettext 'Bug title :') <strong>$BUG</strong> <a href="?id=$id">$(gettext 'Show')</a>
175 $(gettext 'ID - Date :') $id - $DATE
176 $(gettext 'Creator :') <a href="?user=$CREATOR">$CREATOR</a>
177 </pre>
178 EOT
179 fi
180 done
181 done
182 }
184 # Stripped down Wiki parser for bug desc and messages which are simply
185 # displayed in <pre>
186 wiki_parser() {
187 sed \
188 -e s"#http://\([^']*\).png#<img src='\0' alt='[ Image ]' />#"g \
189 -e s"#http://\([^']*\).*# <a href='\0'>\1</a>#"g
190 }
192 # Bug page
193 bug_page() {
194 if [ -f "$PEOPLE/$CREATOR/account.conf" ]; then
195 . $PEOPLE/$CREATOR/account.conf
196 else
197 MAIL="default"
198 fi
199 cat << EOT
200 <h2>$(eval_gettext 'Bug $id')</h2>
201 <form method="get" action="./">
203 <p>
204 $(get_gravatar $MAIL 32)
205 <strong>$STATUS</strong>
206 $BUG - $DATE -
207 $(eval_gettext 'Priority $PRIORITY') -
208 $(eval_ngettext '$msgs message' '$msgs messages' $msgs)
209 </p>
211 <pre>
212 $(echo "$DESC" | wiki_parser)
213 </pre>
215 <div id="tools">
216 EOT
217 if check_auth; then
218 if [ "$STATUS" == "OPEN" ]; then
219 cat << EOT
220 <a href="?id=$id&amp;close">$(gettext "Close bug")</a>
221 <a href="?edit=$id">$(gettext "Edit bug")</a>
222 EOT
223 else
224 cat << EOT
225 <a href="?id=$id&amp;open">$(gettext "Re open bug")</a>
226 EOT
227 fi
228 fi
229 cat << EOT
230 </div>
232 <h3>$(gettext "Messages")</h3>
233 EOT
234 [ "$msgs" == "0" ] && gettext "No messages"
235 for msg in $(ls -1tr $bugdir/$id/msg.*)
236 do
237 . $msg
238 if [ "$MSG" ]; then
239 msgid=$(echo $msg | cut -d "." -f 2)
240 del=""
241 # User can delete his post.
242 [ "$user" == "$USER" ] && \
243 del="<a href=\"?id=$id&amp;delmsg=$msgid\">delete</a>"
244 cat << EOT
245 <p><strong>$USER</strong> $DATE $del</p>
246 <pre>
247 $(echo "$MSG" | wiki_parser)
248 </pre>
249 EOT
250 fi
251 unset NAME DATE MSG
252 done
253 if check_auth; then
254 cat << EOT
255 <div>
256 <h3>$(gettext "New message")</h3>
258 <input type="hidden" name="id" value="$id" />
259 <textarea name="msg" rows="8"></textarea>
260 <p><input type="submit" value="$(gettext 'Send message')" /></p>
261 </form>
262 </div>
263 EOT
264 fi
265 }
267 # Write a new message
268 new_msg() {
269 date=$(date "+%Y-%m-%d %H:%M")
270 msgs=$(ls -1 $bugdir/$id/msg.* | wc -l)
271 count=$(($msgs + 1))
272 if check_auth; then
273 USER="$user"
274 fi
275 sed "s/$(echo -en '\r') /\n/g" > $bugdir/$id/msg.$count << EOT
276 USER="$USER"
277 DATE="$date"
278 MSG="$(GET msg)"
279 EOT
280 }
282 # Create a new Bug
283 new_bug() {
284 count=$(ls -1 $bugdir | wc -l)
285 date=$(date "+%Y-%m-%d %H:%M")
286 # Sanity check, JS may be disabled.
287 [ ! "$(GET bug)" ] && echo "Missing bug title" && exit 1
288 [ ! "$(GET desc)" ] && echo "Missing bug description" && exit 1
289 if check_auth; then
290 USER="$user"
291 fi
292 mkdir -p $bugdir/$count
293 sed "s/$(echo -en '\r') /\n/g" > $bugdir/$count/bug.conf << EOT
294 # SliTaz Bug configuration
296 BUG="$(GET bug)"
297 STATUS="OPEN"
298 PRIORITY="$(GET priority)"
299 CREATOR="$USER"
300 DATE="$date"
301 PKGS="$(GET pkgs)"
303 DESC="$(GET desc)"
304 EOT
305 }
307 # New bug page for the web interface
308 new_bug_page() {
309 cat << EOT
310 <h2>$(gettext "New Bug")</h2>
311 <div id="newbug">
313 <form method="get" action="./" onsubmit="return checkNewBug();">
314 <input type="hidden" name="addbug" />
315 <table>
316 <tbody>
317 <tr>
318 <td>$(gettext "Bug title")*</td>
319 <td><input type="text" name="bug" /></td>
320 </tr>
321 <tr>
322 <td>$(gettext "Description")*</td>
323 <td><textarea name="desc"></textarea></td>
324 </tr>
325 <tr>
326 <td>$(gettext "Packages")</td>
327 <td><input type="text" name="pkgs" /></td>
328 </tr>
329 <tr>
330 <td>$(gettext "Priority")</td>
331 <td>
332 <select name="priority">
333 <option value="standard">$(gettext "Standard")</option>
334 <option value="critical">$(gettext "Critical")</option>
335 </select>
336 <input type="submit" value="$(gettext "Create Bug")" />
337 </td>
338 </tr>
339 </tbody>
340 </table>
341 </form>
343 <p>
344 $(gettext "* field is obligatory. You can also specify affected packages.")
345 </p>
347 </div>
348 EOT
349 }
351 # Edit/Save a bug configuration file
352 edit_bug() {
353 cat << EOT
354 <h2>$(eval_gettext 'Edit Bug $bug')</h2>
355 <div id="edit">
357 <form method="get" action="./">
358 <textarea name="bugconf">$(cat $bugdir/$bug/bug.conf)</textarea>
359 <input type="hidden" name="bug" value="$bug" />
360 <input type="submit" value="$(gettext 'Save configuration')" />
361 </form>
363 </div>
364 EOT
365 }
367 save_bug() {
368 bug="$(GET bug)"
369 content="$(GET bugconf)"
370 sed "s|\"|'|" | sed "s/$(echo -en '\r') /\n/g" > $bugdir/$bug/bug.conf << EOT
371 $content
372 EOT
373 }
375 # Close a fixed bug
376 close_bug() {
377 sed -i s'/OPEN/CLOSED/' $bugdir/$id/bug.conf
378 }
380 # Re open an old bug
381 open_bug() {
382 sed -i s'/CLOSED/OPEN/' $bugdir/$id/bug.conf
383 }
385 # Get and display Gravatar image: get_gravatar email size
386 # Link to profile: <a href="http://www.gravatar.com/$md5">...</a>
387 get_gravatar() {
388 email=$1
389 size=$2
390 [ "$size" ] || size=48
391 url="http://www.gravatar.com/avatar"
392 md5=$(md5crypt $email)
393 echo "<img src=\"$url/$md5?d=identicon&amp;s=$size\" alt=\"\" />"
394 }
396 # Create a new user in AUTH_FILE and PEOPLE
397 new_user_config() {
398 mail="$(GET mail)"
399 pass="$(GET pass)"
400 key=$(echo -n "$user:$mail:$pass" | md5sum | awk '{print $1}')
401 echo "$user:$pass" >> $AUTH_FILE
402 mkdir -p $PEOPLE/$user/
403 cat > $PEOPLE/$user/account.conf << EOT
404 # SliTaz user configuration
405 #
407 NAME="$(GET name)"
408 USER="$user"
409 MAIL="$mail"
410 KEY="$key"
412 COMMUNITY="$(GET scn)"
413 LOCATION="$(GET location)"
414 RELEASES="$(GET releases)"
415 PACKAGES="$(GET packages)"
416 EOT
417 chmod 0600 $PEOPLE/$user/account.conf
418 }
420 #
421 # POST actions
422 #
424 case " $(POST) " in
425 *\ auth\ *)
426 # Authenticate user. Create a session file in $sessions to be used
427 # by check_auth. We have the user login name and a peer session
428 # md5 string in the COOKIE.
429 user="$(POST auth)"
430 pass="$(md5crypt "$(POST pass)")"
431 valid=$(fgrep "${user}:" $AUTH_FILE | cut -d ":" -f 2)
432 if [ "$pass" == "$valid" ] && [ "$pass" != "" ]; then
433 md5session=$(echo -n "$$:$user:$pass:$$" | md5sum | awk '{print $1}')
434 mkdir -p $sessions
435 echo "$md5session" > $sessions/$user
436 header "Location: $WEB_URL" \
437 "Set-Cookie: auth=$user:$md5session; HttpOnly"
438 else
439 header "Location: $WEB_URL?login&error"
440 fi ;;
441 esac
443 #
444 # Plugins
445 #
446 for p in $(ls -1 $plugins)
447 do
448 [ -f "$plugins/$p/$p.conf" ] && . $plugins/$p/$p.conf
449 [ -x "$plugins/$p/$p.cgi" ] && . $plugins/$p/$p.cgi
450 done
452 #
453 # GET actions
454 #
456 case " $(GET) " in
457 *\ README\ *)
458 header
459 html_header
460 user_box
461 echo '<h2>README</h2>'
462 echo '<pre>'
463 cat /usr/share/doc/tazbug/README
464 echo '</pre>'
465 html_footer ;;
466 *\ closed\ *)
467 # Show all closed bugs.
468 header
469 html_header
470 user_box
471 list_bugs CLOSED
472 html_footer ;;
473 *\ login\ *)
474 # The login page
475 [ "$(GET error)" ] && \
476 error="<span class='error'>$(gettext 'Bad login or pass')</span>"
477 header
478 html_header
479 user_box
480 login_page
481 html_footer ;;
482 *\ logout\ *)
483 # Set a Cookie in the past to logout.
484 expires="Expires=Wed, 01-Jan-1980 00:00:00 GMT"
485 if check_auth; then
486 rm -f "$sessions/$user"
487 header "Location: $WEB_URL" "Set-Cookie: auth=none; $expires; HttpOnly"
488 fi ;;
489 *\ user\ *)
490 # User profile
491 header
492 html_header
493 user_box
494 . $PEOPLE/"$(GET user)"/account.conf
495 echo "<h2>$(get_gravatar $MAIL) $(GET user)</h2>"
496 if check_auth && [ "$(GET user)" == "$user" ]; then
497 auth_people
498 else
499 public_people
500 fi
501 html_footer ;;
502 *\ newbug\ *)
503 # Add a bug from web interface.
504 header
505 html_header
506 user_box
507 if check_auth; then
508 new_bug_page
509 else
510 echo "<p>$(gettext 'You must be logged in to post a new bug')</p>"
511 fi
512 html_footer ;;
513 *\ addbug\ *)
514 # Add a bug from web interface.
515 if check_auth; then
516 new_bug
517 header "Location: $WEB_URL?id=$count"
518 fi ;;
519 *\ edit\ *)
520 bug="$(GET edit)"
521 header
522 html_header
523 user_box
524 edit_bug
525 html_footer ;;
526 *\ bugconf\ *)
527 if check_auth; then
528 save_bug
529 header "Location: $WEB_URL?id=$bug"
530 fi ;;
531 *\ id\ *)
532 # Empty deleted messages to keep msg count working.
533 id="$(GET id)"
534 [ "$(GET close)" ] && close_bug
535 [ "$(GET open)" ] && open_bug
536 [ "$(GET msg)" ] && new_msg
537 [ "$(GET delmsg)" ] && rm -f $bugdir/$id/msg.$(GET delmsg) && \
538 touch $bugdir/$id/msg.$(GET delmsg)
539 msgs=$(fgrep MSG= $bugdir/$id/msg.* | wc -l)
540 header
541 html_header
542 user_box
543 . $bugdir/$id/bug.conf
544 bug_page
545 html_footer ;;
546 *\ signup\ *)
547 # Signup
548 header "Content-type: text/plain;"
549 user="$(GET signup)"
550 echo "Requested user login : $user"
551 if fgrep -q "$user:" $AUTH_FILE; then
552 echo "ERROR: User already exists" && exit 1
553 else
554 echo "Creating account for : $(GET name)"
555 new_user_config
556 fi ;;
557 *\ key\ *)
558 # Let user post new bug or message with crypted key (no gettext)
559 #
560 # Testing only and is security acceptable ?
561 #
562 key="$(GET key)"
563 id="$(GET bug)"
564 header "Content-type: text/plain;"
565 echo "Checking secure key..."
566 if fgrep -qH $key $PEOPLE/*/account.conf; then
567 conf=$(fgrep -H $key $PEOPLE/*/account.conf | cut -d ":" -f 1)
568 . $conf
569 echo "Authentified: $NAME ($USER)"
570 case " $(GET) " in
571 *\ msg\ *)
572 [ ! "$id" ] && echo "Missing bug ID" && exit 0
573 echo "Posting new message to bug: $id"
574 echo "Message: $(GET msg)"
575 new_msg ;;
576 *\ bug\ *)
577 echo "Adding new bug: $(GET bug)"
578 echo "Description: $(GET desc)"
579 new_bug ;;
580 esac
581 else
582 echo "Not a valid SliTaz user key"
583 exit 0
584 fi ;;
585 *\ search\ *)
586 header
587 html_header
588 user_box
589 cat << EOT
590 <h2>$(gettext "Search")</h2>
591 <form method="get" action="./">
592 <input type="text" name="search" />
593 <input type="submit" value="$(gettext 'Search')" />
594 </form>
595 <div>
596 EOT
598 #found=0 JS to notify or write results nb under the search box.
599 for bug in $bugdir/*
600 do
601 result=$(fgrep -i "$(GET search)" $bug/*)
602 if [ "$result" ]; then
603 #found=$(($found + 1))
604 id=${bug#bug/}
605 echo "<p><strong>Bug $id</strong> <a href=\"?id=$id\">"$(gettext 'Show')"</a></p>"
606 echo '<pre>'
607 fgrep -i "$(GET search)" $bugdir/$id/* | \
608 sed s"/$(GET search)/<span class='ok'>$(GET search)<\/span>/"g
609 echo '</pre>'
610 else
611 get_search=$(GET search)
612 echo "<p>$(eval_gettext 'No result found for: $get_search')</p>"
613 fi
614 done
615 echo '</div>'
616 html_footer ;;
617 *)
618 # Default page.
619 bugs=$(ls -1 $bugdir | wc -l)
620 close=$(fgrep "CLOSED" $bugdir/*/bug.conf | wc -l)
621 fixme=$(fgrep "OPEN" $bugdir/*/bug.conf | wc -l)
622 msgs=$(find $bugdir -name msg.* ! -size 0 | wc -l)
623 pct=0
624 [ $bugs -gt 0 ] && pct=$(( ($close * 100) / $bugs ))
625 header
626 html_header
627 user_box
628 cat << EOT
630 <h2>$(gettext "Summary")</h2>
632 <p>
633 $(eval_ngettext 'Bug: $bugs in total -' 'Bugs: $bugs in total -' $bugs)
634 $(eval_ngettext '$close fixed -' '$close fixed -' $close)
635 $(eval_ngettext '$fixme to fix -' '$fixme to fix -' $fixme)
636 $(eval_ngettext '$msgs message' '$msgs messages' $msgs)
637 </p>
639 <div class="pctbar">
640 <div class="pct" style="width: ${pct}%;">${pct}%</div>
641 </div>
643 <p>$(gettext "Please read the <a href=\"?README\">README</a> for help and more \
644 information. You may also be interested by the SliTaz \
645 <a href=\"http://roadmap.slitaz.org/\">Roadmap</a> and the packages \
646 <a href=\"http://cook.slitaz.org/\">Cooker</a>. To perform a search \
647 enter your term and press ENTER.")
648 </p>
650 <div id="tools">
651 <a href="?closed">$(gettext 'View closed bugs')</a>
652 EOT
653 if check_auth; then
654 echo "<a href='?newbug'>$(gettext 'Create a new bug')</a>"
655 fi
656 cat << EOT
657 </div>
658 EOT
659 list_bugs OPEN
660 html_footer ;;
661 esac
663 exit 0