unit uUploadPlugin;
interface
uses
Windows, Messages, SysUtils, StrUtils, Classes,
BlckSock, SynSock , SynAUtil,
uUploadAPI, uUploadConsts;
type
TUploadPlugin = class(TInterfacedObject, IUploadPlugin)
private
FSocket: TTCPBlockSocket;
FMessageWnd: HWND;
FCancelSocket: Boolean;
procedure MessageWndMethod(var Message: TMessage);
procedure SocketHeartbeat(Sender: TObject);
public
function Initialize(Reserved: IInterface; var ExtraInfo: WideString; out MessageWindow: HWND): BOOL; stdcall;
function Finalize(Reserved: IInterface; var ExtraInfo: WideString): BOOL; stdcall;
function GetParamI(Index: Integer): Int64; stdcall;
function GetParamS(Index: Integer): WideString; stdcall;
function UploadStream(Stream: ISerialStream; const FileName: WideString; var ExtraInfo: WideString; out URL: WideString): BOOL; stdcall;
procedure ShowSettings(Reserved: IInterface); stdcall;
procedure ShowAboutBox(Reserved: IInterface); stdcall;
property Socket: TTCPBlockSocket read FSocket;
end;
implementation
var log : text;
const
PluginName = 'Domolink PH Sv';
Host = 'ph.orel.ru';
Script = 'http://ph.orel.ru/upload.php';
MainURL = 'http://ph.orel.ru.ru/';
HeartbeatRate = 250;
// В идеале эти константы должны быть доступны для изменения пользователем и считываться из файла
// Settings.ini, находящемся в каталоге с плагином
TimeOut = 30000;
BufSize = DefaultBufSize;
//==================================================================================================
// TUploadPlugin
//==================================================================================================
//==================================================================================================
procedure TUploadPlugin.MessageWndMethod(var Message: TMessage);
begin
if Message.Msg=WM_UPLOAD_TERMINATE
then FCancelSocket:=True
else Message.Result:=DefWindowProc(FMessageWnd, Message.Msg, Message.WParam, Message.LParam)
end;
//==================================================================================================
procedure TUploadPlugin.SocketHeartbeat(Sender: TObject);
procedure StopSocket;
begin
Socket.StopFlag:=True;
FCancelSocket:=True
end;
var
Msg: TMsg;
begin
// Метод, вызываемый сокетом каждый раз в HeartbeatRate мс. и проверяющий, не пришло ли
// окну FMessageWnd сообщений от главной порграммы о необходимости терминировать процесс
// (эта возможность позволяет, например, прервать передачу файла при отсутствии ответа хоста
// без выжидания пользователем истечения всего таймаута TimeOut)
if FCancelSocket
then StopSocket
else while PeekMessage(Msg, FMessageWnd, 0, 0, PM_REMOVE)
do if Msg.Message=WM_UPLOAD_TERMINATE
then StopSocket
else DefWindowProc(FMessageWnd, Msg.Message, Msg.wParam, Msg.lParam)
end;
//==================================================================================================
function TUploadPlugin.Initialize(Reserved: IInterface; var ExtraInfo: WideString; out MessageWindow: HWND): BOOL;
begin
// Создание окна, которому будут посылаться события из главного приложения
FMessageWnd:=AllocateHWnd(MessageWndMethod);
MessageWindow:=FMessageWnd;
FCancelSocket:=False;
Result:=True
end;
//==================================================================================================
function TUploadPlugin.Finalize(Reserved: IInterface; var ExtraInfo: WideString): BOOL;
begin
// Удаление созданного окна
DeallocateHWnd(FMessageWnd);
Result:=True
end;
//==================================================================================================
function TUploadPlugin.GetParamI(Index: Integer): Int64;
begin
// Выдаем основной программе доступные целочисленные параметры плагина
case Index of
// PARAM_SUPPORT_FILES: Result:=1;
PARAM_SUPPORT_IMAGES: Result:=1;
PARAM_MAX_SIZE: Result:=BytesPerGByte;
PARAM_MAX_WIDTH: Result:=5000;
PARAM_MAX_HEIGHT: Result:=5000;
PARAM_SUPPORT_PROXY: Result:=1;
//PARAM_SUPPORT_PROXY: Result:=1;
else Result:=0
end
end;
//==================================================================================================
function TUploadPlugin.GetParamS(Index: Integer): WideString;
begin
// Выдаем основной программе доступные строковые параметры плагина
case Index of
PARAM_NAME: Result:=PluginName;
PARAM_URL: Result:=MainURL;
PARAM_VERSION: Result:='0.1a';
PARAM_COPYRIGHT: Result:='Плагин от северного комьюнити';
PARAM_INFO: Result:='Фотохостинг Domolink';
PARAM_AUTHOR: Result:='GPL © Сентябрь 2009 by Sever.lan community';
PARAM_SUPPORT_EXTS: Result:='.jpg;.jpeg;.png;.gif';
else Result:=''
end
end;
//==================================================================================================
procedure TUploadPlugin.ShowSettings(Reserved: IInterface);
begin
// Показываем диалоговое окно с настройками плагина
MessageBoxW(0, 'Данный плагин не имеет настроек', 'Настройка', MB_ICONINFORMATION or MB_OK)
end;
//==================================================================================================
procedure TUploadPlugin.ShowAboutBox(Reserved: IInterface);
begin
// Показываем диалоговое окно с информацией о плагине
MessageBoxW(0,
'Плагин для загрузки файлов на фейковый обменник '+PluginName,
'О плагине',
MB_ICONINFORMATION or MB_OK)
end;
//==================================================================================================
function TUploadPlugin.UploadStream(Stream: ISerialStream; const FileName: WideString; var ExtraInfo: WideString; out URL: WideString): BOOL;
var
RawStr: string;
function SendStream: Boolean;
var
Buffer: Pointer;
Len ,
Step : Integer;
begin
Result:=False;
// Выделение памяти под буфер Buffer
GetMem(Buffer, BufSize);
try
// Запуск цикла по считыванию буфера Buffer из потока Stream и отправки его в сокет
for Step:=1 to (Stream.Size+BufSize-1) div BufSize
do begin
Len:=Stream.Read(Buffer, BufSize);
if Len=-1
then begin // Посылка данных прервана пользователем
Socket.AbortSocket;
ExtraInfo:=NameError+StrErrorSendAbort;
Exit
end
else Socket.SendBuffer(Buffer, Len)
end;
Result:=True
finally
// Освобождение памяти, занятой буфером Buffer
FreeMem(Buffer, BufSize)
end
end;
function ReadRawStr: Boolean;
begin
RawStr:='';
repeat
RawStr:=RawStr+Socket.RecvPacket(TimeOut);;
until Socket.LastError<>0;
Result:=Socket.LastError<>WSAETIMEDOUT;
if not Result
then ExtraInfo:=NameError+StrErrorTimeout
end;
var
Headers,
Start ,
Finish ,
Bound, link : string;
begin
URL:='';
Result:=False;
//Assign(log, 'T:\bin\modules\upload\Общее\log.txt');
// append(log);
try
//----------------------------------------------------------------------------------------------
// Основное подключение к серверу и отсылка данных
//----------------------------------------------------------------------------------------------
{try }
// Создание сокета, настройка его свойств и подключение к хосту
FSocket:=TTCPBlockSocket.Create;
Socket.OnHeartbeat:=SocketHeartbeat;
Socket.HeartbeatRate:=250;
Socket.Connect(Host, DefaultPort);
if Socket.LastError<>0
then Exit;
// Генерирование разделителя для
Randomize;
Random(MaxInt);
Bound:=IntToHex(Random(MaxInt), 8);
// Составление начальных данных о файле
Start:='--'+Bound+CRLF+
'Content-Disposition: form-data; name="userimg"; filename="'+FileName+'"'+CRLF+CRLF;
// Составление конечных данных о файле
Finish:=CRLF+'--'+Bound+'--'+CRLF;
// Составление заголовков
Headers:='POST '+Script+' HTTP/1.0'+CRLF+
'Host: '+Host+CRLF+
'Referer: http://'+Host+'/'+CRLF+
'User-Agent: '+UserAgent+CRLF+
// При поддержке плагином прокси здесь следует вставить соответствующий заголовок
'Content-Type: multipart/form-data, boundary='+Bound+CRLF+
'Content-Length: '+IntToStr(Integer(Stream.Size)+Length(Start)+Length(Finish))+CRLF+CRLF;
// Посылка заголовков
Socket.SendString(Headers);
// Посылка начальных данных о файле
Socket.SendString(Start);
// Посылка самого файла
if not SendStream
then Exit;
// Посылка конечных данных о файле
Socket.SendString(Finish);
// Приём данных от хоста
if not ReadRawStr then Exit;
// link :='';
// URL:={'http://'+Host+'/'+FileName;} link;
// writeln(log, inttostr( GetLastError));
URL := copy(RawStr, pos('[IMG]',RawStr)+5,
pos('[/IMG]',RawStr) - pos('[IMG]',RawStr)-5 );
Result:=True
finally
Socket.CloseSocket;
FreeAndNil(FSocket);
end
{ except
on E : Exception do
writeln(log,E.ClassName+E.Message);
end; }
end ;
end.