Прием факсов - изящно и просто.
Зачем тратить бумагу и мучать факсы - просто получаем факс и выкладываем на вэб-сервер.
Оговорюсь сразу - hylafax отпал в силу его его "глобальности", надо было простое
и изящное решение.
Его есть у нас - mgetty+sendfax
Исходные данные Freebsd версией посвежее (тестировалось на 7.2 и 8.1),
установленный веб-сервер, модем (желательно не win и внешний, но такие пойдут)
Цель: принимать факсы и выкладывать в удобоваримой форме на веб
Этап установки веб сервера выходит за рамки этой статьи.
Веб-сервер можете выбрать тот который вам по душе.
Маленькое отступление - mgetty+sendfax конфликтует с netpbm. Соответственно принимать факсы
мы сможем,но в tiff, а выкладывать надо в более "понятном" для браузеров формате.
И тут видим что именно netpbm и умеет конвертировть. Ах незадача.. но мы пойдём обходным
путём - мы будем факсы из tiff конвертировать в удобоваримый формат для браузера в png.
Этим будет заниматься tiff2png
Устанавливаем конвертер форматов
Код: Выделить всё
# whereis tiff2png
tiff2png: /usr/ports/graphics/tiff2png
я собирал):(помимо всего у меня в /etc/make.conf указаны такие опции для сборки всех портов
Код: Выделить всё
#cat /etc/make.conf
WITHOUT_X11=YES
WITHOUT_GTK=YES
WITHOUT_GTK2=YES
WITHOUT_IPV6=YES
DISABLE_VULNERABILITIES=YES
Код: Выделить всё
#portinstall tiff2png
Код: Выделить всё
#cd /usr/ports/graphics/tiff2png
#make install clean
Настало время установить "приёмник". Спешу заметить что настройки mgetty+sendfax устанавливаются
интерактивно в момент сборки, т.е. для переконфигурации требуется пересборка. Соответственно
если у вас не заработало с пол-пинка, попробуйте переустановить с нужными параметрами. Лично у
меня заработало сразу с параметрами по умолчанию. Мой модем - внешний акорп 56к.
Выясним как называется файл нашего модема, у меня модем повешен на ком-порт.
соответственно просмотрев список устройств определяем какой наш.
Код: Выделить всё
#ls /dev
мой модем сuau0
если вы не нашли или не знаете какой у вас, mgetty на этапе установки предложит вам выбрать.
Код: Выделить всё
#whereis mgetty+sendfax
mgetty+sendfax: /usr/ports/comms/mgetty+sendfax
Код: Выделить всё
#portinstall mgetty
Код: Выделить всё
#cd /usr/ports/comms/mgetty+sendfax
#make install clean
Диалог выглядит приблизительно так. (в скобках указывается значение по умолчанию)
Код: Выделить всё
#выбор устройства
list of devices: [cuau1] cuau0
#выбор уровня логирования
*** Configuring for port cuau0 ***
- `debug (mgetty)'
This sets the amount of logging `mgetty' will do. A good value is
4, more details are seen with `5', and `9' is really noisy. Try
it! The log data is written to the file `/tmp/log_mg.cuaxx'.: [4]
#ID факса (я написал внутренний номер, на котором висит факс)
- `fax-id'
This sets the fax station ID used in fax mode to identify your
site to the caller (usually this is simply your fax phone number).
: [00 00 000000] 102
#Скорость модема (при необходимости может автоматически понизить до нужной)
- `speed'
Specify, as integer value, the port speed to use. Default is
38400. If the given speed is not valid, `mgetty' complains loudly
and exits.: [38400] 56000
#Опция для модемов Роквел
- `switchbd'
Some modems, mainly Rockwell chipsets, switch to 19200 bps when
entering fax mode. Others may need other speed switches (but I
know none). If your modem is Rockwell based, try `switchbd 19200'
if fax reception doesn't work. (*Warning:* if this is set wrongly,
fax reception will definitely fail. For most sane modems, you do
*not need* this.). Set speed or `0':
#Если ваш модем включен напрямую во внешнюю линию, можете напистать YES,
#для пропуска этапа инициализации модема
- `direct'
Tells mgetty that it is running on a direct line. Mgetty won't try
to initialize any modem, nor will it wait for `RING'. It will just
wait for any character, and then output the issue file and login
prompt. This option is used if you want to connect to machines via
nullmodem cable.: [NO]
#Эта опция осталась для меня загадкой
- `blocking'
Tells mgetty to open the device in `blocking' mode, that is, the
`open()' system call won't succeed until carrier detect is set.
This is set if `mgetty' is called as `getty'. I'm not sure whether
it's very useful, but I include it for completeness: [NO]
#Владелец порта
- `port-owner'
If set, mgetty will `chown' the tty line to the given username (you
can specify a string or an integer uid, but the integer must be
valid). This is highly recommended for security purposes: only
give port access to those users you trust not to misuse your modem
lines!: [uucp]
#Группа порта
- `port-group'
If set, mgetty will `chgrp' the tty line to this group id (which
can be given as group name, or as integer gid). If it's not given,
or not valid, the primary group id of `port-owner'
will be used.: [uucp]
#Права порта
- `port-mode'
Specifies the permissions to `chmod' the device to.
*Never* make a modem device world-accessible, better use `0660'
or even `0600'.: [0660]
#Сброс модема перед стартом
- `toggle-dtr'
Tells mgetty whether it should lower the DTR line upon startup to
reset modem. Default is `yes', but some (few) modems react
allergic to that and crash.: [YES]
#Ожидание перед сбросом
- `toggle-dtr-waittime'
Specifies the time (in ms) to hold the DTR line low.: [500]
#Отключение режима факса в модеме - тут внимательно
- `data-only'
Tells `mgetty' to forget about faxing and only use the data part of
the modem. Default is `false'. You need this if your modem can't
distinguish incoming fax and data calls.: [NO]
#Включение режима модема "только факс"
- `fax-only'
Tells `mgetty' to put the modem in fax-only mode. You need this if
your modem can't distinguish incoming fax and data calls, but you
need fax more important than data; and you need it if you want to
disable data calls for security reasons (this could be achieved
via `login.config' as well): [NO]YES
#Тип модема:
- `modem-type'
Specifies the kind of modem connected to the port. Valid options are:
* auto
Mgetty will detect the modem type itself (which may occasionally
be not desirable, or it may fail on old modem equipment).
* c2.0
Modem is a CLASS 2.0 fax mode. Works better than class 2, if
both are available, because its better standardized. Known to
work with USR and ZyXEL.
* cls2
Modem is a CLASS 2 fax modem, mgetty will not try class 2.0.
* data
Do not try fax initialization
There is no way (yet) to tell mgetty to use *only* fax mode and
refuse data calls with this option, use the `fax-only true'
statement for that.: [auto]
#Строка инициализации модема (тут в некоторых случаях придется посмотреть документацию
#к модему на предмет инициализации)
- `init-chat'
Tells mgetty the chat sequence to use for initializing the modem.
*Warning*: the sequence starts with *expect*, which will in most
cases be `""' (nothing). This ordering was chosen because UUCP
does it this way, and I wanted to avoid confusion here.
Example:
"" \d\d\d+++\d\d\dATQ0E1V1H0 OK ATL0M0S0=0 OK AT&K3 OK
init sequence: ["" ATS0=0Q0&D3&C1 OK]
#Опция для непослушных модемов не реагирующих на АТ
- `force-init-chat'
In some cases, the modem can get stuck in a mode where it won't
react to a simple `AT' command. Usually this happens because the
modem is set to ignore a DTR drop and still has a data connection
to the other side. If you use a voice modem, it could be stuck in
voice mode.
In these situations, the normal `init-chat' will time out, because
the modem won't send the proper responses back.
To get the modem back into a sane state, you can use the
`force-init-chat' chat sequence. The default setup will send the
DLE ETX characters, to get voice modems back to life, and then the
`(pause)+++(pause)ATH0' sequence to get the modem back from data
mode to command mode.
You could prepend this sequence to `init-chat' (it wouldn't harm),
but especially the pauses around the +++ sequence makes this
undesirable slow.:
#Опция для постоянного опроса модема (чтоб не засыпал)
- `modem-check-time'
Some modems have the nasty tendency to crash silently. With this
option, you tell `mgetty' to check every SECONDS seconds with a
simple `AT...OK' sequence whether the modem still reacts. If not,
`mgetty' will restart itself and do a full modem reset.: [3600]
#Количество гудков до подъема трубки модемом
- `rings'
Sets the number of `RING' messages to wait for, before mgetty
picks up the phone. *Warning:* if your modem auto-answers, for
whatever reason, set this to something *different* than the
value set with `ATS0=mmm', otherwise the modems autoanswer and
mgettys manual answer will collide (most modems hang up if a
command is received during auto-answer): [1]
#Согласование модемов
- `answer-chat'
This is the command sequence that is used to answer a phone call.
Usually you can leave it at the default ` "" ATA CONNECT \c \r ',
but for some modems you need `ATS0=1' in place of `ATA' (ATA not
allowed). The extra `\r' expect string is needed that the code can
grab the full CONNECT XYZ\R string. It will work without the \r,
but then the logging information will be less detailed. *Right now,
\r won't work at all, it's not implemented yet. Don't use it.*
: ["" ATA CONNECT \c \r]
#Таймаут
- `answer-chat-timeout'
During the ANSWER-CHAT, each "expect" string must be seen in the
time specified here. Default is 80 seconds. This time should be at
least some 5 seconds longer than the time set with the `ATS7=...'
modem setup command.: [80]
#Жесткое задание скорости:
- `autobauding'
Some modems switch their DTE line speed to the communication line
speed after connecting, e.g., after sending `CONNECT 2400', the
modem switches to 2400 bps. Newer modems usually have a switch to
"lock" a DTE baud rate, which is strongly recommended. If your
modem insists on doing this speed switch, setting `autobauding' to
YES will make mgetty behave accordingly.: [NO]
#Опция для "модема блокиратора"
#(если YES. то при первом звонке не берёт трубку, при втором -берёт)
- `ringback'
If you have to put your modem and your telephone on the same phone
line, you can switch on "ringback" or "ring-twice". This means,
mgetty won't answer the phone on the first call, but remember the
call, and pick up on the second call (if it comes in the time
specified by `ringback-time').: [NO]
#Таймаут "второго звонка"
- `ringback-time'
This setting specifies how much time may pass between the first
and the second call if "ringback" is active.: [30]
- `ignore-carrier'
If your Modem does not assert the DCD (carrier detect) line, or the
serial port or cable or serial driver is broken, it is possible
that `mgetty' or `login' will block after a successful CONNECT
(that means: everything seems to work, but suddenly nothing is sent
to the port anymore. Depending on the operating system used, this
can be before printing the `/etc/issue' file or not before printing
the `password:' prompt.
To work around this, you can switch off the carrier detection in
software: set `ignore-carrier true'. Default is `false'.
*WARNING:* If you use this, your system won't be able to detect
when a caller just hangs up instead of cleanly logging out. This
may result in hanging modems, etc.: [false]
#Что выводить при логине
- `issue-file'
This is the file printed before the login prompt.: [/etc/issue]
#Ожидание перед входом
- `prompt-waittime'
This specifies how long `mgetty' will wait for modem and line to
settle down (in ms) before printing issue file and login prompt: [500]
#Приглашение
- `login-prompt'
This specifies the login prompt that mgetty will output. Some
special characters in this string (and in the issue file, btw) are
recognized and replaced by something else:
* @ system name
* \n newline
* \r carriage return
* \g bell
* \b backspace (ascii 010)
* \f form feed (ascii 013)
* \t TAB
* \P (and \L) port name (e.g. ttyS0)
* \C date and time, in "ctime()" format
* \I Connection string (e.g. 2400/REL)
* \N (and \U) number of users currently logged in
* \S Port speed (e.g. 38400)
* \D current date in dd/mm/yy format
* \T current time in hh:mm:ss format
* \DIGIT character with the specified octal code
The maximum lenght of the login prompt is limited to 140
characters (after expansion).: [@!login: ]
#Ожидание логина
- `login-time'
This specifies the maximum time the user can take to log in. If no
login has occured after that time, `mgetty' will hang up.: [240]
#Какая-то специфика для зикселей
- `fax-server-file'
Specifies the fax file(s) that is to be sent if someone else calls
your modem in *fax polling mode*, that is, the caller *receives* a
document.
Normally, the file given is a text file, containing the list of G3
files to send to the calling machine, one file per line. Comment
lines (starting with "#") are ignored. For backward compatibility,
`mgetty' does check whether the named file is a G3 file itself, in
which case this file is sent directly (but then, you can only send
one page).
Not all modems support fax poll *server* mode, I know that the
ZyXEL and MultiTech do.:
#Размер ограничений на директорию факсов
- `diskspace'
This setting tells mgetty the minimum amount of disk space (in KB) that
has to be available in the fax spool directory for fax reception
to be allowed.: [1024]
#Отсылка уведомления по мылу о пришедшем факсе
- `notify'
This is the address that will get mails if a fax is received. Not
fully tested.: [faxadmin]
#Права владельца на файлы факсов
- `fax-owner'
If set, mgetty will `chown' the received files to the given username
(you can specify a string or an integer uid, but the integer must be
valid).: [uucp]
#Права групы для файлов факса
- `fax-group'
If set, mgetty will `chgrp' the received files to this group id
(which can be given as group name, or as integer gid).: [modem] nogroup
#Права на файл
- `fax-mode'
Specifies the permissions to `chmod' the received files.: [0660]
#Уровень отладки (логирования)
- `fax-mode'
Specifies the permissions to `chmod' the received files.: [0660]
#Опять что-то по поводу инициализации модема
- `modem-init'
Specifies an `AT...' command that is to be sent to the modem right
at the *beginning* of all modem talk (even before setting the modem
into fax mode, so this could be an `ATZ' if you want to reset the
modem).:
#Окончание инициализации, команда
- `modem-handshake'
Specifies an `AT...' command that will be sent to the modem at the
*end* of the modem initialization, right before dialing. *Do not
use ATZ or such here*, since resetting the modem will switch off
fax mode.: [AT&H3]
#Попытки при принятии "некоректных" факсов
- `max-tries'
Specify the maximum number of tries per page if the receiving end
reports reception errors. If NNN tries do not suffice to
successfully transmit a page, `sendfax' will give up or simply go
on, depending on the setting of `max-tries-continue' (see below).
If this is set to `0', `sendfax' will ignore retransmission
requests and simply go on.: [3]
For "mission critical" faxes, I'd set it to NO, but since the page
quality is most often quite good even if reported as "page bad",
the default is YES.: [YES]
#Скорость при факс-режиме (максимальная)
- `speed'
Set the port speed to use for fax send operations. Usually,
`38400' is a good choice, but a few dumb modems (for example, some
based on rockwell chipsets) need `19200' or even `9600'. A few
modems can go higher, but `sendfax' may not support it, and it may
not always work.: [38400]
#Префикс при исходящем звонке (нам оно не надо)
- `dial-prefix'
This is the command used for dialing out. Usually this will be
something simple, as `ATD' or `ATDP', but if you have an unusual
setup, it could also be something like `ATX0DP0;X4DT' (meaning:
switch off dial-tone detection, pulse-dial `0', back to command
mode, switch on dial-tone detection, and go ahead dialing with
touch tones). The phone number will be sent right after the
`dial-prefix'.: [ATD]
#Директория для факсов
- `poll-dir'
This is used to specify a directory where polled faxes (wheather
maps and such) are to be saved into. Default is the current
directory.: [./]
#"Красота факсов"
- `normal-res'
If set to `yes' or `true' (boolean), `sendfax' won't attempt to
make a fax connection in "fine resolution" mode. Normally you
won't need to use that option, since `faxrunq' will set the `-n'
switch if needed.: [NO]
#Логирование в stdout
- `verbose'
If set to `yes' or `true', `sendfax' will output progress reports
on stdout, if set to `no', `sendfax' will only print error and
warning messages.: [NO]
#Ну и финал, посмотрели, всё ли правильно указали, и жмём Y
Settings for port cuau0
------------------------
debug 4
fax-id 111
speed 56000
direct NO
blocking NO
port-owner uucp
port-group uucp
port-mode 0660
toggle-dtr YES
toggle-dtr-waittime 500
data-only NO
fax-only YES
modem-type auto
init-chat "" ATS0=0Q0&D3&C1 OK
modem-check-time 3600
rings 1
answer-chat "" ATA CONNECT \c \r
answer-chat-timeout 80
autobauding NO
ringback NO
ringback-time 30
ignore-carrier false
issue-file /etc/issue
prompt-waittime 500
login-prompt @!login:
login-time 240
diskspace 1024
notify faxadmin
fax-owner uucp
fax-group modem
fax-mode 0660
fax-id 00 00 000000
modem-type auto
debug 4
modem-handshake AT&H3
max-tries 3
max-tries-continue YES
speed 38400
dial-prefix ATD
poll-dir ./
normal-res NO
verbose NO
OK?: [y]
Настроим конвертацию факсов сначала в tiff, а потом в png
По умолчанию mgetty+sendfax после приёма факса выполняет скрипт new_fax из директории
/usr/local/lib/mgetty+sendfax/. Tам же в директории samples лежат примеры
таких скриптов.Bы можете создать свой собственный. У меня он имеет такой вид.
Скрипт для преобразования факса в картинку png, переноса в директорию
веб сервера, и формирования структуры html страниц
Код: Выделить всё
#!/bin/sh
#Скрипт выполняется при каждом приходе факса
###Настройка
#Куда мылить при приходе нового факса
MAILTO="root@mydomain.ru"
###переменные
MONTH=`date +"%m"`
MONTH_MOD=0
DATE=`date +"%d.%m.%Y"`
DAY_OF_MONTH=`date +"%d"`
#на всяк
PATH=$PATH:/usr/bin
DATE_HM=`date +"%d.%m.%Y %H:%M"`
###Файлы
#Логируем
FLOG=/var/log/fax/fax.log
#Куда будем складывать png и формировать директории для html с факсами
#Тут подразумевается директория веэб-сервера
FAX_DIR=/usr/local/www/fax
#служебные файлы
BSY=$FAX_DIR/fax2html.bsy
CMD=$FAX_DIR/fax2html.cmd
#директория для пришедшего факса
DIRECTORY=$FAX_DIR/$DATE
###Пути к бинарникам
#мылер
MAILER=/usr/sbin/sendmail
###Параметры
#$1-txit-code; $2-отправитель ID; $3-кол-во страниц
HUP=$1
SENDER=$2
PAGES=$3
### Изменение в index.html если сменилась дата
case $MONTH in
01) MONTH="Январе";;
02) MONTH="Феврале";;
03) MONTH="Марте";;
04) MONTH="Апреле";;
05) MONTH="Мае";;
06) MONTH="Июне";;
07) MONTH="Июле";;
08) MONTH="Августе";;
09) MONTH="Сентябре";;
10) MONTH="Октябре";;
11) MONTH="Ноябре";;
12) MONTH="Декабре";;
esac
#втыкаем новый месяц в index.html
cat $FAX_DIR/index.html | grep "$MONTH" >> /dev/null && MONTH_MOD=1
### cat $FAX_DIR/index.html | grep "$MONTH" > /tmp/test.txt
if [ "$MONTH_MOD" = "0" ]; then
# SED-command
echo "/<\/"BODY">/i\\" > $CMD
echo "<H2 ALIGN=CENTER>"$MONTH"<\/H2>\\" >> $CMD
cp $FAX_DIR/index.html $FAX_DIR/index.prev
sed -f $CMD $FAX_DIR/index.prev > $FAX_DIR/index.html
fi
rm -f $CMD
#создаём папку с датой
if [ ! -d $DIRECTORY ]; then
mkdir $DIRECTORY
cp $FAX_DIR/skel.index $DIRECTORY
echo "/<\/"HEAD">/i\\" > $CMD
echo "<TITLE>"$DATE"</TITLE>" >> $CMD
sed -f $CMD $DIRECTORY/skel.index > $DIRECTORY/index.html
rm -f $DIRECTORY/skel.index
if [ ! -f $FAX_DIR/index.prev ]; then
cp $FAX_DIR/index.html $FAX_DIR/index.prev
fi
rm -f $CMD
echo "/<\/"BODY">/i\\" > $CMD
echo "<A HREF=$DATE>"$DATE"</A>" >> $CMD
sed -f $CMD $FAX_DIR/index.prev > $FAX_DIR/index.html
fi
rm -f $FAX_DIR/index.prev
rm -f /tmp/test.txt
rm -f $CMD
# Логируем
echo `date +"%d.%m.%Y %r"`"receive fax from $SENDER, $PAGES pages, \
rc $HUP" >> $FLOG
# выходим если страниц нет
[ "$PAGES" = "0" ] && exit $HUP
# Проверка наличия служебного файла, если есть - засыпаем, и по новой
while [ -f $BSY ]
do
echo `date +"%d.%m.%Y %r"` "lock found" >> $FLOG
sleep 5
done
# Создаём служебный файл
touch $BSY
# Преобразуем факс
shift 3
I=1
#постранично
while [ $I -le $PAGES ]
do
FULL_FAX_NAME=$1
FAX_NAME=`basename $FULL_FAX_NAME`
RES=`basename $FULL_FAX_NAME | sed 's/.\(.\).*/\1/'`
# Если в нормальном - стречим
if [ $RES = n ]; then
STRETCH="-s" ; else
STRETCH=""
fi
# если не пустой конвертим сначала в tiff, потом в png,
#создаём миниатюру, складываем в папку с датой
if [ -s $FULL_FAX_NAME ]
then
/usr/local/bin/fax2tiff $STRETCH -M -f -o $DIRECTORY/$FAX_NAME.tiff \
$FULL_FAX_NAME | /usr/local/bin/tiff2png
echo $DIRECTORY/$FAX_NAME.tiff >> /tmp/1
/usr/local/bin/tiff2png -d $DIRECTORY $DIRECTORY/$FAX_NAME.tiff \
> /dev/null 2>&1
echo $DIRECTORY/$FAX_NAME.png >> /tmp/1
cp /usr/local/www/fax/1.gif $FAX_DIR/$DATE/$FAX_NAME-r.gif >/dev/null 2>&1
# формируем команду для вставки ссылки в index.html
echo "/<\/"BODY">/i\\" > $CMD.
echo "<A HREF=\""$FAX_NAME".html\">""<IMG SRC=\""$FAX_NAME"-r.gif\" \
ALIGN = top></A>\\" >> $CMD
echo "<EM>"`date +"%r"`"</EM> От: "$SENDER "(" $I "стр.)\\" >> $CMD
if [ "$HUP" != "0" ];then
echo "<FONT COLOR=#FF0000>Ошибка "$HUP"</FONT>\\" >> $CMD
fi
echo "<BR><BR>" >> $CMD
fi
echo "<BR><BR>" >> $CMD
# Если файл пустой - вставляем ссылку что он битый
else
echo "/<\/"BODY">/i\\" > $CMD
echo "<IMG SRC=\"/icons/broken.gif\" ALIGN = top>\\" >> $CMD
echo "(" $I "стр.)<BR><BR>" >> $CMD
fi
cp $DIRECTORY/index.html $DIRECTORY/index.prev
#выполняем сформированную команду
sed -f $CMD $DIRECTORY/index.prev > $DIRECTORY/index.html
rm -f $CMD
# Вставляем картинку в html
echo "/<\/"BODY">/i\\" > $CMD
echo "<IMG SRC = \""$FAX_NAME.png"\" WIDTH=100%>" >> $CMD
sed -f $CMD $FAX_DIR/skel.index > $DIRECTORY/$FAX_NAME.html
shift
I=`expr $I + 1`
done
#удаляем промежуточные и служебные файлы
rm -f $FULL_FAX_NAME
rm -f $DIRECTORY/index.prev
rm -f $CMD
rm -f $BSY
exit 0
(скелетон для html)и миниатюра 1.gif (положите какую хотите)
Код: Выделить всё
#cat skel.index
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=koi8-r">
</HEAD>
<BODY leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0" marginwidth="0">
</BODY>
</HTML>
улучшению\изменению - всегда рады
Соответственно веб-сервер обязан быть настроен должным образом
(содержать необходимые директории).
Огроманая просьба - в коментах не обсуждать - ссылка на обсуждение в форуме