Облако тегов:

2е блюдо (1) альбом (14) анимация (1) биссероплетение (10) блокнот (3) браузер (2) бумага (13) видео (1) вирус (1) витражи (1) выпечка (1) вязание (43) гадание (3) глина (1) декор (2) делаем (4) диски (2) е-версии (1) журналы/газеты (1) закон РФ (2) запуск (1) зубочистки (1) интересно (1) картинки (1) квиллинг (4) квилтинг (4) классно (13) команды (1) композиция (1) конвертор (2) коробочка (17) кружево (1) крючок (7) кукла (3) кулинария (1) кусудама (3) лепим (1) литература (1) лого (1) манга (1) мультиварка (2) нитка (1) новый год (2) носки (17) обучение (1) оптимизация (1) оригами (2) основы (4) открытка (13) папье-маше (1) ПД (2) пейзаж (1) переплет (2) перплет (2) платье (1) плетение (1) ПО (4) поделка (7) поделки (5) принтер (1) программирование (3) Р/м (1) рельеф (1) салаты (1) сингл (1) скачать (2) скорость интернета (1) спицехранилище (1) ссылки (1) сумка (7) тапочки (10) терминал (2) хлеб (1) холодный фарфор (2) цветок (2) цветы (7) шитьё (5) шрифт (1) шрифты (1) шьем (2) эволюция (1) autoit (1) bat (1) BellyDance (1) CD (4) scrapbooking (48) ubuntu (5) unix (1) windows (1)
Показаны сообщения с ярлыком программирование. Показать все сообщения
Показаны сообщения с ярлыком программирование. Показать все сообщения

29 апреля 2012 г.

Autoit. Программа для написания простеньких программок и скриптов. С руководством

Autoit
Русское сообщество

В Autoit существует только один тип данных - Variant , поэтому для удобства написания скриптов рекомендуется использовать следующие имена переменных:

Первый набор символов после знака доллара ($) должен определять тип данных. Следующий список определяет префиксы и типы данных, используемых с ними:

  • $a<символ> - (Array) Массив данных -  последующий символ, взятый из списка ниже, определяет тип данных в массиве
  • $b - (Binary data) Двоичные данные
  • $h - (File or window handle) Дескриптор файла, окна и т.д.
  • $i - (Integer) Целое число
  • $f - (Boolean) Логический тип, может принимать значения True или False
  • $n - (Floating point number) Число с плавающей точкой
  • $s - (String) Строка
  • $v - (Variant) Вариант, неопределенный тип данных, базовый тип для Autoit
  • $t - (Struct) Структура в стиле C/C++, для использования в DllCall, в сообщениях WM_*, при обработке данных и т.п.
  • $p - (Pointer) Указатель на структуру или на её элемент
Остальное имя переменной следует начинать с заглавной буквы, и оно должно отражать функциональность (свойства) переменной. Имена вроде “$iC” неприемлемы.
"$aiWeekDayNames" или "$iCounter" намного предпочтительнее.

для работы с системой
для работы с системой






4 сентября 2011 г.

Свой Web-PDF принтер за 10 минут

(c)


Как потратить совсем немного времени и сделать что-нибудь простое и оригинальное, поражающее своей глобальностью — но абсолютно бесполезное? Очень просто. Давайте сделаем свой принтер.

Нам понадобится (кроме головы и рук) только работающий web-сервер с поддержкой cgi-bin, к которому у нас есть доступ по FTP. Есть такой? Поехали!




Создаем в папочке cgi-bin скрипт printer. Содержание скрипта очень простое:


#! /usr/bin/perl

use strict;

if (!defined($ENV{'CONTENT_TYPE'}) || $ENV{'CONTENT_TYPE'} ne "application/ipp") {
    print "Content-Type: text/html\n\n";
    print ":-)";
    exit;
}

# $d - входные данные в виде строки
# $l - длина строки входных данных
# $i - текущая позиция разбора данных
# %a - разобранные атрибуты

my ($d, $l, $i, %a) = ("", 0, 0);
binmode STDIN;
$l += read(STDIN, $d, 4096, $l) while (!eof(STDIN));

parseRequest(\$d, \$l, \$i, \%a);

my $o = ""
 . substr($d, 0, 2) # version
 . chr(0x00) . chr(0x00) # status
 . substr($d, 4, 4) # request
 . chr(0x01) # attributes
 . stringAttribute(0x47, "attributes-charset", "utf-8")
 . stringAttribute(0x48, "attributes-natural-language", "en-us")
 . chr(0x04) # attributes
 . stringAttribute(0x42, "printer-name", "PDF")
 . chr(0x03) # end
 . chr(0x0a)
;

print "Content-Type: text/html\n";
print "Content-Length: " . length($o) . "\n";
print "\n";
print $o;

if (defined($a{'-status'}) && $a{'-status'} == 0x02 && $i < $l) {
    my @t = localtime;
    my $output = sprintf("../pdf/%04d%02d%02d-%02d%02d%02d.pdf", $t[5] + 1900, $t[4], $t[3], $t[2], $t[1], $t[0]);
    if (open(P, "|-", "gs", "-q", "-dBATCH", "-dNOPAUSE", "-dSAFER", "-sDEVICE=pdfwrite", "-sOutputFile=$output", "-")) {
        binmode P;
        print P substr($d, $i);
        close P;
    }
}

sub parseRequest {
    my ($d, $l, $i, $a) = @_;
    return if $$i >= $$l - 2;
    $$a{'-version'} = (ord(substr($$d, $$i, 1)) << 8) + ord(substr($$d, $$i + 1, 1)); $$i += 2;
    return if $$i >= $$l - 2;
    $$a{'-status'} = (ord(substr($$d, $$i, 1)) << 8) + ord(substr($$d, $$i + 1, 1)); $$i += 2;
    return if $$i >= $$l - 4;
    $$a{'-request'} = parseInt(substr($$d, $$i, 4)); $$i += 4;
    return if $$i >= $$l - 1;
    my $what = ord(substr($$d, $$i, 1)); $$i ++;
    return parseAttributes($d, $l, $i, $a) if ($what == 0x01);
}

sub parseAttributes {
    my ($d, $l, $i, $a) = @_;
    while ($$i < $$l) {
        my $what = ord(substr($$d, $$i, 1)); $$i ++;
        return if ($what == 0x03);
        return parseAttributes($d, $l, $i, $a) if ($what == 0x02);
        return parseAttributes($d, $l, $i, $a) if ($what == 0x04);
        return if $$i >= $$l - 2;
        my $key_len = (ord(substr($$d, $$i, 1)) << 8) + ord(substr($$d, $$i + 1, 1)); $$i += 2;
        return if $$i >= $$l - $key_len;
        my $key = substr($$d, $$i, $key_len); $$i += $key_len;
        return if $$i >= $$l - 2;
        my $val_len = (ord(substr($$d, $$i, 1)) << 8) + ord(substr($$d, $$i + 1, 1)); $$i += 2;
        return if $$i >= $$l - $val_len;
        my $val = substr($$d, $$i, $val_len); $$i += $val_len;
        $$a{$key} = $val;
    }
}

sub parseInt {
    my $v = shift;
    my $l = length($v);
    my $r = 0;
    for (my $i = $l; $i > 0; $i --) {
        $r += ( (1 << (($i - 1) * 8)) * ord(substr($v, $l - $i, 1)) );
    }
    $r -= 4294967296 if ($r >= 2147483648);
    return $r;
}

sub stringLength {
    my $s = shift;
    my $l = length($s);
    my $i1 = $l & 0xFF;
    $l = ($l - $i1) >> 8;
    my $i2 = $l & 0xFF;
    return chr($i2) . chr($i1);
}

sub stringAttribute {
    my ($type, $key, $val) = @_;
    return chr($type) . stringLength($key) . $key . stringLength($val) . $val;
}


Как видите, никаких внешних зависимостей от модулей Perl, и ничего лишнего. Фактически, нужны только Perl и программа gs, которые есть практически везде.

Скрипт когда-то был основан на PHP::Print::IPP. Но, так как на большинстве серверов выполнять внешние программы из PHP-скриптов запрещено, то пришлось переписать на Perl. Скрипт реализует самую-самую базовую функциональность IPP-сервера.

Далее, даем права на исполнение скрипта (755, или rwxr-xr-x). Смотрим в браузере: http://www.site.ru/cgi-bin/printer. Работает? Хорошо.

Еще создадим папку pdf в корне сайта и установим права на запись к этой папке (777, или rwxrwxrwx).

Теперь добавляем принтер в Windows:

  • Установка принтера
  • Сетевой принтер или принтер, подключенный к другому компьютеру
  • Подключиться к принтеру в Интернете, в домашней сети или в интрасети: http://www.site.ru/cgi-bin/printer
  • Изготовитель: Generic, модель: MS Publisher Imagesetter
И печатаем пробную страницу. В папочке pdf на сервере появляется наша пробная страница.

Аналогичным образом можно напечатать много чего. Документы, картинки… Все, что угодно.

Осталось сделать три замечания.

1. Теоретически, скрипт может не работать, по самым разным причинам. Основные принципы отладки Perl-скриптов оставлю на самостоятельное изучение.
2. Желательно переименовать скрипт printer в какой-нибудь более хитрый, чтобы все подряд не печатали на Вашем принтере. Через .htaccess закрыть доступ к CGI-скрипту достаточно сложно, сделать авторизацию внутри Perl-скрипта тоже. А то можно было бы...
3. Принтер нормально работает под Windows Vista и Linux. Установка, в целом, не такая уж и сложная. Но вот нужно ли это?..

UPD: По многочисленным просьбам, выкладываю версию на PHP.
Необходимо включить в php.ini always_populate_raw_post_data = On и не отключать возможность выполнять popen.

<?

if (!isset($_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != "application/ipp") {
    header("Content-Type: text/html");
    print ":-)";
    exit;
}

# $d - входные данные в виде строки
# $l - длина строки входных данных
# $i - текущая позиция разбора данных
# %a - разобранные атрибуты

$d = &$HTTP_RAW_POST_DATA;
$l = strlen($d);
$i = 0;
$a = array();

parseRequest($d, $l, $i, $a);

$o = ""
 . substr($d, 0, 2) # version
 . chr(0x00) . chr(0x00) # status
 . substr($d, 4, 4) # request
 . chr(0x01) # attributes
 . stringAttribute(0x47, "attributes-charset", "utf-8")
 . stringAttribute(0x48, "attributes-natural-language", "en-us")
 . chr(0x04) # attributes
 . stringAttribute(0x42, "printer-name", "PDF")
 . chr(0x03) # end
 . chr(0x0a)
;

header("Content-Type: text/html");
header("Content-Length: " . strlen($o));
print $o;

if (isset($a['-status']) && $a['-status'] == 0x02 && $i < $l) {
    $output = sprintf("pdf/%s.pdf", date("Ymd-His"));
    if ($P = popen("gs -q -dBATCH -dNOPAUSE -dSAFER -sDEVICE=pdfwrite -sOutputFile=$output -", "w")) {
        fwrite($P, substr($d, $i));
        fclose($P);
    }
}

function parseRequest(&$d, &$l, &$i, &$a) {
    if ($i >= $l - 2) return;
    $a['-version'] = (ord($d[$i]) << 8) + ord($d[$i + 1]); $i += 2;
    if ($i >= $l - 2) return;
    $a['-status'] = (ord($d[$i]) << 8) + ord($d[$i + 1]); $i += 2;
    if ($i >= $l - 4) return;
    $a['-request'] = parseInt(substr($d, $i, 4)); $i += 4;
    if ($i >= $l - 1) return;
    $what = ord($d[$i]); $i ++;
    if ($what == 0x01) return parseAttributes($d, $l, $i, $a);
}

function parseAttributes(&$d, &$l, &$i, &$a) {
    while ($i < $l) {
        $what = ord($d[$i]); $i ++;
        if ($what == 0x03) return;
        if ($what == 0x02) return parseAttributes($d, $l, $i, $a);
        if ($what == 0x04) return parseAttributes($d, $l, $i, $a);
        if ($i >= $l - 2) return;
        $key_len = (ord($d[$i]) << 8) + ord($d[$i + 1]); $i += 2;
        if ($i >= $l - $key_len) return;
        $key = substr($d, $i, $key_len); $i += $key_len;
        if ($i >= $l - 2) return;
        $val_len = (ord($d[$i]) << 8) + ord($d[$i + 1]); $i += 2;
        if ($i >= $l - $val_len) return;
        $val = substr($d, $i, $val_len); $i += $val_len;
        $a[$key] = $val;
    }
}

function parseInt($v) {
    $r = 0;
    $l = strlen($v);
    for ($i = $l; $i > 0; $i --) {
        $r += ( (1 << (($i - 1) * 8)) * ord($v[$l - $i]) );
    }
    if ($r >= 2147483648) $r -= 4294967296;
    return $r;
}

function stringLength($s) {
    $l = strlen($s);
    $i1 = $l & 0xFF;
    $l = ($l - $i1) >> 8;
    $i2 = $l & 0xFF;
    return chr($i2) . chr($i1);
}

function stringAttribute($type, $key, $val) {
    return chr($type) . stringLength($key) . $key . stringLength($val) . $val;
}

?>

Для продвинутых пользователей. Если пробовать запускать скрипт на Windows-сервере, то, возможно, понадобится указать полный путь к интерпретатору gs. При этом слэши в пути должны быть обратными: «C:\\Program files\\\gs\\gs8.71\\bin\\gs.exe». То же самое касается файла PDF. Потому что, хоть PHP сам по себе и понимает файлы с прямыми слэшами, этого нельзя сказать об интерпретаторе командной строки Windows.

Многопользовательский чат на BAT

(c) Ненормальное программирование
Был период, когда в универе задали сделать несколько чатов. В зависимости от вариантов, были заданы различные способы взаимодействия программ от сокетов до майлслотов (mailslot). Когда задания были прикончены, остались силы взяться за скрипты BAT. Вот что получилось…



Всё что нужно для запуска:
1. Взять код по ссылке в конце статьи
2. Сохранить код в файл *.bat
3. Положить файл в сетевую папку
4. Запустить файл с разных компов (можно и с одного)

В комментариях предложили использовать совместно с DropBox, но говорят — что работает весьма не быстро.



Прежде всего, хочу извиниться за код, оформленный скриншотами. Просто никто не подсветит BAT-ник лучше, чем это делает Notepad++. Снимки кода сохранены в палитровые (256 цветов) PNG — вес скринов кода по 5-10Кб.


Сперва про реализацию


Базовые элементы:
1. %chat% — имя группы
2. %nick% — имя пользователя
3. файл "%chat%_history" — файл с полной историей группы
4. файл "%chat%" — файл с последней репликой в группе
5. файл "%chat%_cs" — файл используемый для синхронизации

Для начала спросим пользователя ввести имя группы и свой ник. После получения имени группы и ника в строке №5 производится запуск скриптом самого себя с тремя параметрами: слово talk_widget, а также имя группы и имя пользователя.



Теперь выводим в заголовке окна название группы и имя пользователя (строка №3). Если существует файл с именем %chat%_history, печатаем его содержимое на экран (строка №4). Далее в цикле считываем содержимое файла %chat% и сравниваем его с тем, что было в предыдущем считывании. Если содержимое файла изменилось — печатаем его на экран.



Изначально код имеет следующую структуру: при запуске проверяются параметры, если первым параметром идёт слово «talk_widget», то скрипт выполняет код, относящийся к отправке текста. При отсутствии такового параметра, код выполняет функцию получения и отображения данных. Изначально производится запуск скрипта без параметров, он спрашивает имя группы и имя пользователя, запускает второй процесс с параметром «talk_widget», а сам начинает печатать содержимое чат-группы.



Теперь о том, как работает код принимающий ввод от пользователя. Он сперва модифицирует заголовок окна (строка №5). Затем печатает в файл последней реплики сообщение-уведомление о своём подключении и дописывает сообщение к истории. При доступе к файлу реплики используется примитивный механизм критических секций (чуть ниже рассмотрим, как он работает). Далее в цикле (строки 11-19) производится получение от пользователя строк данных и их запись в файл реплики и допись в файл истории.



Функция входа в критическую секцию в файл, используемый для синхронизации, циклично записывает случайное число. До тех пор пока оно не окажется там при повторном считывании. Если на момент запуска функции файл существует, также осуществляется небольшая задержка. Задержки реализуются через ping>nul.



Функция выхода из критической секции просто удаляет файл синхронизации.



Теперь про результат


Имеется чат, обладающий следующими качествами:
1. Разделение по чат-группам (много групп и много пользователей)
2. Получение истории общения новыми участниками
3. Общение по сети (выложить скрипт в расшаренную папку и запустить с разных компьютеров)

При запуске, скрипт спрашивает имя чат-группы и имя пользователя.



После ввода требуемых данных, появляется второе окно, служащее консолью для ввода:



Теперь запущу этот же BAT-файл (он лежит в расшаренной папке) с другого компьютера сети.



После ввода того же самого имени чата и имени нового пользователя опять же появится второе окно для ввода данных на отправку.



Теперь попробуем пересылать сообщения между абонентами:



Теперь подключимся с третьего компьютера:



И увидим следующую картину:



Внимание! Замечен непонятный баг в win7 x64 при запуске скрипта из сетевой папки //***. Третья строка скрипта pushd "%~dp0" интерпретируется очень долго. Очень долго разбирается %~dp0, попробуйте просто echo %~dp0 вызвать — это как минимум странно. Если подождать минуты 2-3, то всё будет работать нормально... в WinXP таких проблем нет.

Предупреждение: при каждом запуске скрипта из сетевой папки в «Моём Компьютере» будут плодиться сетевые диски с буквами Z: Y: X: и т.д. После перезагрузки они пропадут без следа.

код:
 

@rem BatChat
@echo off
cls
pushd "%~dp0"
echo Current DIR: "%CD%"
if "%~1" == "talk_widget" goto talker

rem ================================================

rem ////////////////////
:auth
echo Enter chat filename to connect ("abc" for example):
set /p chat=^>
echo Enter your nick:
set /p nick=^>
start call %0 talk_widget %chat% %nick%

rem ////////////////////
:listener
cls
call title "| Chat: %chat% | User: %nick% |"
if exist %chat%_history type %chat%_history
if not exist %chat% echo. 2>%chat%

:listener_loop
ping 127.0.0.1 -n 1 -w 20 > nul
set oldtext=%text%
set /p text=<%chat%
if not "%text%" == "%oldtext%" echo %text%
goto listener_loop
rem ////////////////////

rem ================================================

rem ////////////////////
rem // %2 - chat name //
rem // %3 - user nick //
rem ////////////////////
:talker
set chat=%~2
set nick=%~3
cls
call title "| Chat: %chat% | User: %nick% |"
call ::cs_in
echo (%TIME% %nick% connected)>%chat%
call ::cs_out
echo (%TIME% %nick% connected)>>%chat%_history

:talker_loop
cls
echo Dear %nick%, type message to send:
set /p msg=^>
call ::cs_in
echo [%TIME% %nick%]: %msg%>%chat%
call ::cs_out
echo [%TIME% %nick%]: %msg%>>%chat%_history
goto talker_loop
rem ////////////////////

rem ================================================

rem ////////////////////
:cs_in
if exist "%chat%_cs" ping 127.0.0.1 -n 1 -w 50 > nul
set cs_value=%RANDOM%

:cs_in_loop
echo %cs_value%>%chat%_cs
set /p ret=<%chat%_cs
if "%ret%" == "%cs_value%" exit /b
ping 127.0.0.1 -n 1 -w 10 > nul
goto :cs_in_loop
rem ////////////////////

rem ////////////////////
:cs_out
del %chat%_cs
exit /b
rem ////////////////////

rem ================================================