Sisyphus repositório
Última atualização: 1 outubro 2023 | SRPMs: 18631 | Visitas: 37861759
en ru br
ALT Linux repositórios
S:0.18-alt1
5.0: 0.7-alt1
4.1: 0.6-alt2.M41.5
4.0: 0.4-alt2

Group :: Sistema/Configurações/Rede
RPM: alterator-net-wifi

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs e FR  Repocop 

alterator-net-wifi-0.14/000075500000000000000000000000001175167571700151725ustar00rootroot00000000000000alterator-net-wifi-0.14/Makefile000064400000000000000000000004051175167571700166310ustar00rootroot00000000000000NAME=net-wifi
DESCRIPTION="Wi-Fi setup"

INSTALL=/usr/bin/install

all:
clean:
install: install-backend install-po install-ui

include /usr/share/alterator/build/po.mak
include /usr/share/alterator/build/ui2.mak
include /usr/share/alterator/build/backend.mak

alterator-net-wifi-0.14/applications/000075500000000000000000000000001175167571700176605ustar00rootroot00000000000000alterator-net-wifi-0.14/applications/net-wifi.desktop000064400000000000000000000004011175167571700227700ustar00rootroot00000000000000[Desktop Entry]
Type=Application
Categories=X-Alterator-Hidden
Icon=net-wifi
Terminal=false
Name=Wifi interfaces
X-Alterator-URI=/net-wifi
X-Alterator-Weight=30
X-Alterator-Help=net-wifi
Name[ru]=Wifi интерфейсы
Name[uk]=Wifi інтерфейси
alterator-net-wifi-0.14/backend3/000075500000000000000000000000001175167571700166445ustar00rootroot00000000000000alterator-net-wifi-0.14/backend3/net-wifi000075500000000000000000000271111175167571700203160ustar00rootroot00000000000000#!/bin/sh

#turn off auto expansion
set -f

alterator_api_version=1
. alterator-sh-functions
. alterator-hw-functions

. shell-config

BR=' '

#########

exit_handler()
{
local rc=$?
trap - EXIT
[ -n "$WATCH_PID" ] && kill "$WATCH_PID" 2>/dev/null
exit $rc
}

trap exit_handler HUP INT QUIT TERM EXIT


### supplicant utilities

supplicant_request(){
local iface="$1"; shift
wpa_cli -i "$iface" "$@"
}

supplicant_read_status(){
local iface="$1";shift
local status=

if ! status="$(supplicant_request "$iface" status)";then
echo "`_ "connection is not configured"`"
return 0
fi

echo "$status" |
{
local SSID=
local BSSID=
local STATE=
local IP=
while read line; do
case "$line" in
ssid=*)
SSID="${line##ssid=}"
;;
bssid=*)
BSSID="${line##bssid=}"
;;
wpa_state=*)
STATE="${line##wpa_state=}"
;;
ip_address=*)
IP="${line##ip_address=}"
;;
esac
done
case "$STATE" in
COMPLETED)
printf "`_ "connected to network \"%s\"(%s)\n"`" "$SSID" "$BSSID"
;;
SCANNING)
echo "`_ "scanning for available networks..."`"
;;
ASSOCIATING|ASSOCIATED|4WAY_HANDSHAKE|GROUP_HANDSHAKE)
echo "`_ "connecting to network..."`"
;;
DISCONNECTED|INACTIVE)
echo "`_ "disconnected"`"
;;
*)
echo "$STATE"
esac
}
}


#########


configure_interface()
{
local iface="$1"

echo "configuring interface $iface..." >&2

local ifacedir="/etc/net/ifaces/$iface"
local options="$ifacedir/options"
local supp_conf="$ifacedir/wpa_supplicant.conf"

#prepare interface
[ -d "$ifacedir" ] || mkdir "$ifacedir"

shell_config_set "$options" "DISABLED" "no"
shell_config_set "$options" "USE_IFPLUGD" "no"
shell_config_set "$options" "NM_CONTROLLED" "no"
shell_config_set "$options" "TYPE" "eth" #wi-fi devices has strange names
shell_config_set "$options" "WPA_DRIVER" "wext"

shell_config_set "$supp_conf" "ctrl_interface" "/var/run/wpa_supplicant"
shell_config_set "$supp_conf" "update_config" "1"
chmod 600 "$supp_conf"

wpa_cli ping -i"$iface" > /dev/null ||
wpa_supplicant -B -Dwext -i"$iface" -c"$supp_conf"
}

MBSENT="/usr/bin/alterator-mailbox-send"
supplicant_watch()
{
[ -x "$MBSENT" ] || return
while true;do
$MBSENT 'wpa-supplicant'
sleep 3
done
}

make_psk(){
wpa_passphrase "$1" "$2" | awk -F'=' '/^[[:space:]]*psk=/{print $2}'
}

#########

scan_results=""

get_scan_results(){
scan_results="$(supplicant_request "$1" scan_results | sed '1d')"
}

list_scan_results()
{
#bssid / frequency / signal level / flags / ssid
[ -n "$scan_results" ] || get_scan_results "$1" > /dev/null

echo "$scan_results" |\
while read bssid frequency level flags ssid x; do
echo "$level $ssid $ssid ($bssid)${mrk}%%${flags}%%"
done | sort -g -r | sed '/%%.*WPA.*%%/s,%%.*%%,\[X\],; /%%.WPA.*%%/!s,%%.*%%,\[+\],; s,^\([0-9]\+\)[ ]\+\(.*)\)\(.*\)$,\2\*\1\3,;'
}

list_networks()
{
#network id / ssid / bssid / flags
# ssid can be empty! Use "-"
supplicant_request "$1" list_networks | sed '1d;s/\t\t/\t-\t/' |
while read id ssid bssid flags; do
[ "$ssid" == "-" ] && ssid=""
local label=
if [ "$flags" = "[DISABLED]" ]; then
label="-- $ssid"
else
label="+ $ssid"
fi
if [ "$flags" = "[CURRENT]" ]; then
label="* $ssid"
fi
echo "$id" "$label"
done
}

list_auth_types()
{
#WPA-PSK WPA-EAP IEEE8021X WPA-NONE NONE
for i in $(supplicant_request "$1" get_capability key_mgmt);do
case "$i" in
NONE)
echo "nopasswd `_ "No password"`"
echo "wep `_ "WEP Password"`"
;;
WPA-PSK)
echo "wpa-psk `_ "WPA Personal (WPA-PSK)"`"
echo "wpa2-psk `_ "WPA2 Personal (WPA-PSK)"`"
;;
# WPA-EAP)
# echo "wpa-eap `_ "WPA Enterprise (WPA-EAP)"`"
# echo "wpa2-eap `_ "WPA2 Enterprise (WPA-EAP)"`"
# ;;
esac
done
}

list_eap_methods(){
supplicant_request "$1" get_capability eap | tr -s ' ' '\n'
}

list_pairwise_types(){
supplicant_request "$1" get_capability pairwise | tr -s ' ' '\n'
}

#connection status


new_name=

#network information
read_network()
{
local iface="$1";shift
local id="${new_name:-${1:-0}}"; shift # use new_name if exists
[ "$id" != "-1" ] || id="0"
new_name=
local value=

write_string_param "name" "$id"

# ssid can be empty! Use "-"
supplicant_request "$iface" list_networks | sed '1d;s/\t\t/\t-\t/' |
while read net_id ssid bssid flags; do
[ "$net_id" = "$id" ] || continue

[ "$ssid" != "-" ] || ssid=""

write_string_param "bssid" "$bssid"

[ "$flags" = "[DISABLED]" ] &&\
write_bool_param "enabled" "no" ||\
write_bool_param "enabled" "yes"

[ "$flags" = "[CURRENT]" ] &&\
write_string_param "current" "`_ "Current network"`" ||\
write_string_param "current" ""
break
done

value="$(supplicant_request "$iface" get_network "$id" ssid | tr -d '"')"
[ "$value" = "FAIL" ] || write_string_param "essid" "$value"

value="$(supplicant_request "$iface" get_network "$id" pairwise)"
[ "$value" = "FAIL" ] || write_string_param "pairwise" "$value"

local key_mgmt="$(supplicant_request "$iface" get_network "$id" key_mgmt)"
local proto="$(supplicant_request "$iface" get_network "$id" "proto")"

case "$key_mgmt" in
NONE)
value="$(supplicant_request "$iface" get_network "$id" wep_key0)"

if [ "$value" = "FAIL" -o -z "$value" ]; then
write_string_param "auth_type" "nopasswd"
else
write_string_param "auth_type" "wep"
fi
;;
WPA-PSK)
if [ "$proto" = "RSN" -o "$proto" = "WPA2" ]; then
write_string_param "auth_type" "wpa2-psk"
else
write_string_param "auth_type" "wpa-psk"
fi
;;
WPA-EAP)
if [ "$proto" = "RSN" -o "$proto" = "WPA2" ]; then
write_string_param "auth_type" "wpa2-eap"
else
write_string_param "auth_type" "wpa-eap"
fi
;;
esac
}

write_network()
{
local iface="$1";shift

if test_bool "$in_enabled"; then
supplicant_request "$iface" enable "$in_name" > /dev/null
else
supplicant_request "$iface" disable "$in_name" > /dev/null
fi

supplicant_request "$iface" set_network "$in_name" ssid "\"$in_essid\"" >/dev/null
supplicant_request "$iface" set_network "$in_name" scan_ssid 1 >/dev/null

local passwd_error=0;

case "$in_auth_type" in
nopasswd)
supplicant_request "$iface" set_network "$in_name" key_mgmt "NONE" >/dev/null
supplicant_request "$iface" set_network "$in_name" wep_key0 "\"\"" >/dev/null
;;
wep)
supplicant_request "$iface" set_network "$in_name" key_mgmt "NONE" >/dev/null
[ -n "$in_key" ] &&
supplicant_request "$iface" set_network "$in_name" wep_key0 "$in_key" >/dev/null
;;
wpa-psk|wpa2-psk)
supplicant_request "$iface" set_network "$in_name" key_mgmt "WPA-PSK" >/dev/null
supplicant_request "$iface" set_network "$in_name" pairwise "$in_pairwise" >/dev/null

# Меняем пароль, только если он не пуст и wpa_passphrase не
# отдает пустой hash (короткий пароль)
# Такие пароли supplicant может записывать в конф.файл, но читать такой файл
# уже не сможет!!!
# Кроме того, нельзя допускать, чтобы при записи новой сети с wpa-psk пароль оставался
# пустым!!!

# Установим пароль, если он не пуст
if [ -n "$in_key" ]; then
local hash=$(make_psk "$in_essid" "$in_key")
if [ -n "$hash" ]; then
supplicant_request "$iface" set_network "$in_name" psk "$hash" >/dev/null
else
# короткий пароль -- надо ругаться!
passwd_error=1
fi
fi

# Если пароля так и нет
local passwd=$(supplicant_request "$iface" get_network "$in_name" psk)
if [ "$passwd" != "*" ]; then
# Принимаем крайне меры, а то все упадет...
supplicant_request "$iface" set_network "$in_name" psk "\"password\"" >/dev/null
fi

if [ "$in_auth_type" = "wpa-psk" ];then
supplicant_request "$iface" set_network "$in_name" proto "WPA" >/dev/null
else
supplicant_request "$iface" set_network "$in_name" proto "WPA2" >/dev/null
fi
;;
esac

supplicant_request "$iface" save_config >/dev/null
return $passwd_error
}

configured_iface=

on_message()
{
if [ "$in_action" = "read" -o "$in_action" = "write" -o "$in_action" = "list" ]; then
if [ -z "$in_iface" ] || ! netdev_is_wireless "$in_iface"; then
write_error "`_ "Not a wireless interface"`"
return
fi
fi

if [ -n "$in_iface" -a "$in_iface" != "$configured_iface" ]; then
configure_interface "$in_iface"
configured_iface="$in_iface"
fi

case "$in_action" in

monitor)
if [ -z "$WATCH_PID" -a "$in_mode" = "on" ]; then
supplicant_watch&
WATCH_PID=$!
else
[ -n "$WATCH_PID" ] && kill "$WATCH_PID"
WATCH_PID=
fi
;;

list)
case "${in__objects}" in
scan_results)
list_scan_results "$in_iface" | write_enum
write_enum_item "" "`_ "Other network"`"
;;
networks) list_networks "$in_iface" | write_enum ;;
auth_types) list_auth_types "$in_iface" | write_enum ;;
pairwise_types) list_pairwise_types "$in_iface" | write_enum ;;
eap_methods) list_eap_methods "$in_iface" | write_enum ;;
esac
;;

read)
write_string_param iface "$in_iface"
write_string_param iface_status "$(supplicant_read_status "$in_iface")"
read_network "$in_iface" "$in_name"
;;

write)
[ -n "$in_select" ] &&\
read_network "$in_iface" "$in_name"

if [ -n "$in_btn_apply" ]; then
if ! write_network "$in_iface"; then
write_error "`_ "Password is too short"`"
return
fi
elif [ -n "$in_btn_delete" ]; then
supplicant_request "$in_iface" disable "$in_name" > /dev/null
supplicant_request "$in_iface" remove_network "$in_name" >/dev/null
supplicant_request "$in_iface" save_config >/dev/null
new_name=$((in_name-1))
[ $(( $new_name < 0 )) == "1" ] && new_name=0
elif [ -n "$in_btn_reconfigure" ]; then
supplicant_request "$in_iface" reconfigure >/dev/null
elif [ -n "$in_btn_rescan" ]; then
supplicant_request "$in_iface" scan >/dev/null
get_scan_results "$in_iface" >/dev/null
elif [ -n "$in_btn_new" ]; then
local id="$(supplicant_request "$in_iface" add_network)"
if [ "$id" = "FAIL" ]; then
write_error "`_ "Unable to create network"`"
return
fi
new_name="$id"
in_name="$id"
in_essid="$in_scanned_net"
local flags="$(echo "$scan_results" | awk -F"$BR" "\"$in_scanned_net\" == \$5 {print \$4}")"
in_enabled="#t"

in_auth_type="nopasswd"
if [ "${flags/WEP}" != "$flags" ]; then in_auth_type="wep";fi
if [ "${flags/WPA-PSK}" != "$flags" ]; then in_auth_type="wpa-psk";fi
if [ "${flags/WPA2-PSK}" != "$flags" ]; then in_auth_type="wpa2-psk";fi
if [ "$in_auth_type" == "wpa-psk" -o "$in_auth_type" == "wpa2-psk" ]; then
in_pairwise="TKIP"
if [ "${flags/CCMP}" != "$flags" ]; then in_pairwise="CCMP"; fi
fi
write_network "$in_iface"
fi
;;

esac
}

message_loop
alterator-net-wifi-0.14/ui/000075500000000000000000000000001175167571700156075ustar00rootroot00000000000000alterator-net-wifi-0.14/ui/net-wifi/000075500000000000000000000000001175167571700173315ustar00rootroot00000000000000alterator-net-wifi-0.14/ui/net-wifi/ajax.scm000064400000000000000000000047001175167571700207610ustar00rootroot00000000000000(define-module (ui net-wifi ajax)
:use-module (alterator ajax)
:use-module (alterator woo)
:use-module (alterator card-index)
:use-module (alterator algo)
:export (init))

(define (ui-read)
(f-reset "/net-wifi" 'iface (form-value "iface") 'name (form-value "name"))
(update-activity))

(define (update-networks)
(f-update-ci-list "name" "/net-wifi/networks" 'iface (form-value "iface"))
(ui-read) )

(define (ui-write)
(f-submit "/net-wifi" 'iface (form-value "iface") 'btn_apply ".")
(update-networks))


(define (update-status)
(form-update-value-list `("iface_status")
(woo-read-first "/net-wifi" 'iface (form-value "iface")))
; (form-set-timeout update-status 2))
)

(define (update-activity)
(let ((auth (form-value "auth_type")))
(and (string? auth)
(form-update-activity "key" (not (string=? auth "nopasswd")) )
(form-update-activity "pairwise" (not (or (string=? auth "nopasswd")
(string=? auth "wep")))) )))

;;;

(define (ui-reconfigure)
(catch/message (thunk
(woo-write "/net-wifi" 'iface (form-value "iface") 'btn_reconfigure "." )))
(update-networks) )

(define (ui-delete)
(catch/message (thunk
(woo-write "/net-wifi" 'iface (form-value "iface")
'name (form-value "name")
'btn_delete "." )))
(update-networks) )

(define (ui-rescan)
(catch/message (thunk
(woo-write "/net-wifi" 'iface (form-value "iface") 'btn_rescan "." )
(f-update-list "scan-results" "/net-wifi/scan_results" 'iface (form-value "iface"))) ))

(define (ui-new)
(catch/message (thunk
(woo-write "/net-wifi" 'iface (form-value "iface")
'btn_new "."
'scanned_net (form-value "scan-results"))))
(update-networks) )

;;;


(define (init)
(form-bind "name" "change" update-networks)
(form-bind "auth_type" "change" update-activity)

(form-bind "btn_reconfigure" "click" ui-reconfigure)
(form-bind "btn_apply" "click" ui-write)
(form-bind "btn_reset" "click" ui-read)
(form-bind "btn_delete" "click" ui-delete)
(form-bind "btn_rescan" "click" ui-rescan)
(form-bind "btn_new" "click" ui-new)

(f-update-list "auth_type" "/net-wifi/auth_types" 'iface (form-value "iface"))
(f-update-list "pairwise" "/net-wifi/pairwise_types" 'iface (form-value "iface"))
(update-networks)
(ui-rescan)
(update-status) )



alterator-net-wifi-0.14/ui/net-wifi/index.html000064400000000000000000000043031175167571700213260ustar00rootroot00000000000000<html wf="none">
<body>

<form method="POST">

<p><span translate="_">Interface:</span>
<b><span class="alterator-label" name="iface"/></b>
<input type="button" class="btn" name="btn_reconfigure" value="Reconfigure interface"/>
</p>

<p><span translate="_">Status:</span>
<span class="alterator-label" name="iface_status"/></p>

<h2><span translate="_">Configured networks</span></h2>

<p><table width="100%">
<tr><td style="width:30%">
<select name="name" size="10"/><br/>
</td><td>
<table>
<tr><td align="left"><b><span class="alterator-label" name="current"/></b></td>
<td><input type="checkbox" name="enabled" value="#t"/>
<span translate="_">Enable</span> </td></tr>
<tr><td align="right"><span translate="_">Network name:</span></td>
<td><input type="text" name="essid"/></td></tr>
<!--<tr><td align="right"><span translate="_">Access point</span>:</td>
<td><input type="text" name="bssid"/></td></tr>-->
<tr><td align="right"><span translate="_">Auth type:</span></td>
<td><select name="auth_type" enumref="/net-wifi/auth_types"/></td></tr>
<tr><td align="right"><span translate="_" name="key">Change password:</span></td>
<td><input type="text" name="key"/></td></tr>
<tr><td align="right"><span translate="_" name="pairwise">Encryption:</span></td>
<td><select name="pairwise" enumref="/net-wifi/pairwise_types"/></td></tr>
<tr><td colspan="2">
<input type="button" name="btn_apply" value="Apply" class="btn"/>
<input type="button" name="btn_reset" value="Reset" class="btn"/>
<input type="button" name="btn_delete" value="Delete" class="btn"/>
</td></tr>
</table>
</td></tr>
</table></p>

<h2><span translate="_">Configure new network</span></h2>

<p><span translate="_">Networks found:</span>
<select name="scan-results" enumref="/net-wifi/scan_results"/>
<input type="button" class="btn" name="btn_rescan" value="Rescan"/>
<input type="button" class="btn" name="btn_new" value="Configure"/></p>

</form>

</body>
</html>
alterator-net-wifi-0.14/ui/net-wifi/index.scm000064400000000000000000000121521175167571700211450ustar00rootroot00000000000000width 800
height 600

(document:surround "/std/frame")
(document:insert "/std/functions")

(define *iface* (global 'iface))
(define *networks* (make-cell '()))


(define (update-networks)
(catch/message (thunk
(cell-set! *networks* (woo-list "/net-wifi/networks" 'iface *iface*))))
(let ((n (form-value "networks")))
(form-update-enum "networks" (cell-ref *networks*))
(form-update-value "networks" n))
(if (string=? "" (form-value "networks"))
(if (pair? (cell-ref *networks*))
(form-update-value "networks"
(woo-get-option (car (cell-ref *networks*)) 'name) ))))

(define (reset-from-backend)
(catch/message (thunk
(let ((data
(woo-read-first "/net-wifi" 'iface *iface* 'name (form-value "networks"))))
(form-update-value "iface" (bold *iface*))
(form-update-value "current" (bold (woo-get-option data 'current)))
(form-update-value "status" (woo-get-option data 'iface_status))
(form-update-value "enable-cb" (woo-get-option data 'enabled))
(form-update-value "essid" (woo-get-option data 'essid ""))
(form-update-value "auth_type" (woo-get-option data 'auth_type))
(form-update-value "key" "")
(form-update-value "pairwise" (woo-get-option data 'pairwise ""))
(update-activity) ))))

(define (write-to-backend)
(catch/message
(thunk (woo-write "/net-wifi"
'btn_apply "."
'iface *iface*
'enabled (form-value "enable-cb")
'essid (form-value "essid")
'auth_type (form-value "auth_type")
'key (form-value "key")
'pairwise (form-value "pairwise")
'name (form-value "networks"))
(update-networks)
(reset-from-backend))))



(define (update-activity)
(let ((auth (form-value "auth_type")))
(form-update-activity "key" (not (string=? auth "nopasswd")) )
(form-update-activity "pairwise" (not (or (string=? auth "nopasswd")
(string=? auth "wep")))) ))

;;;

(define (ui-reconfigure)
(catch/message (thunk
(woo-write "/net-wifi" 'iface *iface* 'btn_reconfigure "." )))
(update-networks)
(reset-from-backend))

(define (ui-delete)
(catch/message (thunk
(woo-write "/net-wifi" 'iface *iface*
'name (form-value "networks")
'btn_delete "." )))
(update-networks)
(reset-from-backend) )

(define (ui-rescan)
(catch/message (thunk
(woo-write "/net-wifi" 'iface *iface* 'btn_rescan "." )
(form-update-enum "scan-results" (woo-list "/net-wifi/scan_results" 'iface *iface*)) )))

(define (ui-new)
(catch/message (thunk
(woo-write "/net-wifi" 'iface *iface*
'btn_new "."
'scanned_net (form-value "scan-results"))))
(update-networks)
(reset-from-backend) )

;;; widgets!

(gridbox columns "0;100"

(label (_ "Interface:") nameref "iface")
(label name "iface")

(label (_ "Status:") nameref "status")
(label name "status" text-wrap #t)

(spacer)
(button align "right" text (_ "Reconfigure interface") (when clicked (ui-reconfigure))))

(groupbox (_ "Configured networks")

(gridbox columns "30;70"

(listbox name "networks" (when selected (reset-from-backend) ))
(gridbox columns "0;100"

(spacer)
(label name "current")

(spacer)
(checkbox text (_ "Enable") name "enable-cb")

(label (_ "Network name:") nameref "essid")
(edit name "essid")

(label (_ "Auth type:") nameref "auth_type")
(combobox name "auth_type" (when selected (update-activity)))

(label (_ "Change password:") nameref "key")
(edit "" name "key")

(label (_ "Encryption:") nameref "pairwise")
(combobox name "pairwise")

(spacer)
(gridbox columns "100;0;0;0" (spacer)
(button text (_ "Apply") (when clicked (write-to-backend)))
(button text (_ "Reset") (when clicked (reset-from-backend)))
(button text (_ "Delete") (when clicked (ui-delete))))
)))

(label (string-append "<b>" (_ "Configure new network") "</b>"))


(gridbox columns "0;90;10;0"
(label) (label (string-append (_ "Name") " (MAC) * " (_ "signal") " [" (_ "authentication") "]" )) (label) (label)
(label (_ "Networks found:"))
(combobox name "scan-results")
(button text (_ "Rescan") (when clicked (ui-rescan)))
(button text (_ "Configure") (when clicked (ui-new))))

(button (_ "OK")
align "left"
(when clicked
(woo-try "monitor" "/net-wifi" 'mode "off")
(remove-mailbox message-handler)
(document:end)))

;;;


(define (message-handler args)
(and (eq? (car args) 'wpa-supplicant)
(catch/message (lambda()
(update-networks)
(form-update-value "status"
(woo-get-option
(woo-read-first "/net-wifi" 'iface *iface*) 'iface_status))))))

(document:root (when loaded
(catch/message (thunk
(form-update-enum "auth_type" (woo-list "/net-wifi/auth_types" 'iface *iface*))
(form-update-enum "pairwise" (woo-list "/net-wifi/pairwise_types" 'iface *iface*)) ))
(ui-rescan)
(update-networks)
(reset-from-backend)
(woo-try "monitor" "/net-wifi" 'mode "on")
(add-mailbox message-handler)
))


 
projeto & código: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
mantenedor atual: Michael Shigorin
mantenedor da tradução: Fernando Martini aka fmartini © 2009