![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
|||
|
|||
|
При работе с потоками меня смущает один момент. Когда мне нужно произвести авторизованное действие, то я в каждом потоке авторизуюсь и произвожу какое-то действие. Естественно - это колоссальное количество ненужных авторизаций. Каким образом можно производить действия с одной авторизации? Для наглядности ниже код, который отправляет публичные сообщения пользователям популярного форумного движка. Каким образом нужно модифицировать этот код, чтобы авторизовывался я только один раз, а постинг происходил в многопоточном режиме. Собственно код:
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,
StdCtrls, ComCtrls, Gauges, SyncObjs, IdCookieManager, ActiveX, VBScript_RegExp_55_TLB;
type
TForm1 = class(TForm)
Edit1: TEdit;
UpDown1: TUpDown;
Button1: TButton;
Label1: TLabel;
OpenDialog1: TOpenDialog;
GoodLabel: TLabel;
IdHTTP1: TIdHTTP;
Gauge1: TGauge;
Button2: TButton;
Memo1: TMemo;
IdCookieManager1: TIdCookieManager;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TNewThread = class(TThread)
private
FAcc : string;
page:string;
session,security,u,u2,lastcomment:string;
protected
procedure Execute; override;
public
procedure Sync;
constructor Create(CreateSuspended: Boolean);
function Parse(page:string; pattern:string):string;
end;
var
Form1: TForm1;
Accounts:Tstringlist;
Thread, Acc:integer;
Work:boolean;
CS:TcriticalSection;
implementation
{$R *.dfm}
constructor TNewThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
end;
procedure TForm1.Button1Click(Sender: TObject); // Подготовка аккаунтов
begin
OpenDialog1.InitialDir:=ExtractFilePath(Application.ExeName);
if OpenDialog1.Execute then
begin
Accounts.Clear;
Accounts.LoadFromFile(OpenDialog1.FileName);
Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
GoodLabel.Caption:='0'; //Тут будут отправленные
Gauge1.MaxValue:=Accounts.Count; //Всего - количество для спама
Gauge1.Progress:=0; //Текущий указатель
Work:=true; //Запускаем
for Thread:=1 to strtoint(Edit1.Text) do //Устанавливаем количество потоков
TNewThread.Create(false);
Thread:=strtoint(Edit1.Text);
end;
procedure TNewThread.Execute;
var CurAcc:integer;
data:Tstringlist;
HTTP: TIdHTTP;
CookieManager:TIdCookieManager;
begin
CoInitialize(nil);
while Work do
begin
CS.Enter;
Inc(Acc);
if Acc<Accounts.Count then CurAcc:=Acc else Work:=false;
CS.Leave;
if Work then
begin
FAcc:= Accounts[CurAcc]; //Тут текущий аккаунт
data:=tstringlist.Create;
HTTP:=tidHTTP.Create();
CookieManager:=tidCookieManager.Create();
HTTP.AllowCookies:=true;
HTTP.CookieManager:=CookieManager;
HTTP.HandleRedirects:=true;
HTTP.Request.UserAgent:='Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13';
page:=HTTP.Get('http://forums.bla-bla-bla.com/index.php');
session:=Parse(page,'name="s" value="(.*)"');
security:=Parse(page,'name="securitytoken" value="(.*)"');
data.Add('vb_login_username=USERNAME');
data.Add('cookieuser=1');
data.Add('vb_login_password=');
data.Add('s='+session);
data.Add('securitytoken='+security);
data.Add('do=login');
data.Add('vb_login_md5password=0945fc9611f55fd0e183fb8b144f1afe');
data.Add('vb_login_md5password_utf=0945fc9611f55fd0e183fb8b144f1afe');
HTTP.Post('http://forums.bla-bla-bla.com/login.php?do=login',data);
data.Clear;
page:=HTTP.Get(trim(Facc));
security:=Parse(page,'name="securitytoken" value="(.*)"');
u:=Parse(page,'name="u" value="(.*)"');
u2:=Parse(page,'name="u2" value="(.*)"');
lastcomment:=Parse(page,'name="lastcomment" value="(.*)"');
data.Add('ajax=1');
data.Add('wysiwyg=0');
data.Add('styleid=0');
data.Add('fromquickcomment=1');
data.Add('s=');
data.Add('securitytoken='+security);
data.Add('do=message');
data.Add('u='+u);
data.Add('u2='+u2);
data.Add('loggedinuser='+u);
data.Add('parseurl=1');
data.Add('lastcomment='+lastcomment);
data.Add('allow_ajax_qc=1');
data.Add('fromconverse=');
data.Add('message=MESSAGE');
try
HTTP.Post('http://forums.bla-bla-bla.com/visitormessage.php?do=message',data);
data.Clear;
finally
data.Free;
HTTP.Free;
CookieManager.Free;
end;
Synchronize(Sync);
end;
end;
dec(Thread);
if Thread=0 then ShowMessage('OK');
end;
function TNewThread.Parse(page, pattern: string): string;
var
Reg: TRegExp;
mc: MatchCollection;
m: Match;
sm: SubMatches;
i:Integer;
s,r:string;
begin
Reg := TRegExp.Create(Form1);
try
//Reg.Pattern := 'name="s" value="(.*)"';
s:=page;
Reg.Pattern:=pattern;
Reg.IgnoreCase:=true;
Reg.Global:=true;
Reg.Multiline:=true;
mc:=Reg.Execute(s) as MatchCollection;
for I := 0 to mc.Count - 1 do begin
//ShowMessage(inttostr(mc.Count));
m:=mc[i] as Match;
sm:=m.SubMatches as SubMatches;
r:=trim(VarToStr(sm[0]));
Result:=r;
end;
finally
m:=nil;
sm:=nil;
mc:=nil;
Reg.Free;
end;
end;
procedure TNewThread.Sync;
begin
Form1.GoodLabel.Caption:=IntToStr(StrToInt(Form1.GoodLabel.Caption)+1);
Form1.Gauge1.Progress:=Form1.Gauge1.Progress+1;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Accounts.Free;
CS.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Accounts:=Tstringlist.create;
CS:=TcriticalSection.create;
end;
end. |
|
#2
|
||||
|
||||
|
ну так после авторизации запоминай глобально securitytoken и куки и используй их в потоках для постинга.
|
|
#3
|
|||
|
|||
|
Я в каждом потоке сначала создаю HTTP потом освобождаю. Если не буду освобождать то ведь будет ошибка? А если буду - то ничего не останется.
|
|
#4
|
||||
|
||||
|
Создай один раз глобально и не освобождай
|
|
#5
|
|||
|
|||
|
Хм. Попробую. Только что-то туплю. Ну не буду я его освобождать... И получиться что в моём HTTP одновременно два десятка разных действий возможно? Или его создавать в private класса? Совсем запутался...
![]() |
|
#6
|
||||
|
||||
|
когда-то я так это дело писал. отправляет сообщения в чат форума (не этого!!!). при нажатии на кнопку с начала логинимся (можно тожа в потоке
), потом создаем потоки TPostThread для каждого сообщения из мемы1. в мему2 добавляются отправленые сообщения для контроля.Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdHTTP, IdCookieManager;
type
TPostThread = class(TThread)
private
FMsg: String;
FSleep: Cardinal;
procedure Updt;
protected
procedure Execute; override;
public
constructor Create(AMsg: String; ASleep: Cardinal);
end;
TForm1 = class(TForm)
EditUser: TEdit;
EditPass: TEdit;
IdHTTP: TIdHTTP;
Button1: TButton;
IdCookieManager: TIdCookieManager;
Memo1: TMemo;
Memo2: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
FSecuritytoken: String = '';
FCookie: String = '';
implementation
{$R *.dfm}
function StringToHex(s: String): String;
var
i: Integer;
begin
Result:='';
for i:=1 to Length(s) do Result:=Result+'%'+IntToHex(Ord(s[i]), 2);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
stringstream: TStringStream;
s: String;
i: Integer;
begin
stringstream:=TStringStream.Create('vb_login_username='+StringToHex(EditUser.Text)+'&vb_login_password='+StringToHex(EditPass.Text)+'&cookieuser=1&s=&securitytoken=guest&do=login&vb_login_md5password=&vb_login_md5password_utf=');
try
IdHTTP.Request.ContentType:='application/x-www-form-urlencoded';
IdHTTP.Request.ContentLength:=stringstream.Size;
IdHTTP.Post('http://forum.ru/login.php?do=login', stringstream);
IdHTTP.Request.ContentType:='';
IdHTTP.Request.ContentLength:=-1;
s:=IdHTTP.Get('http://forum.ru/index.php');
i:=Pos('<input type="hidden" name="securitytoken" value="', s);
if i>0 then
begin
s:=Copy(s, i+49, Length(s));
s:=Copy(s, 1, Pos('"', s)-1);
if (s<>'') and (s<>'guest') then
begin
FSecuritytoken:=s;
FCookie:='';
for i:=0 to IdCookieManager.CookieCollection.Count-1 do
FCookie:=FCookie+IdCookieManager.CookieCollection.Items[i].CookieName+'='+IdCookieManager.CookieCollection.Items[i].Value+'; ';
FCookie:=Trim(FCookie);
for i:=0 to Memo1.Lines.Count-1 do TPostThread.Create(Memo1.Lines[i], i*5000);
end;
end;
finally
stringstream.Free;
end;
end;
{ TPostThread }
constructor TPostThread.Create(AMsg: String; ASleep: Cardinal);
begin
inherited Create(True);
FreeOnTerminate:=True;
FMsg:=AMsg;
FSleep:=ASleep;
Resume;
end;
procedure TPostThread.Execute;
var
IdHTTP: TIdHTTP;
stringstream: TStringStream;
begin
Sleep(FSleep);
try
IdHTTP:=TIdHTTP.Create(nil);
IdHTTP.Request.CustomHeaders.Text:='Cookie: '+FCookie;
IdHTTP.HandleRedirects:=True;
IdHTTP.Request.ContentType:='application/x-www-form-urlencoded';
IdHTTP.Request.ContentLength:=stringstream.Size;
stringstream:=TStringStream.Create('do=shout&message='+StringToHex(FMsg)+'&securitytoken='+FSecuritytoken);
try
IdHTTP.Post('http://forum.ru/infernoshout.php', stringstream);
finally
stringstream.Free;
IdHTTP.Free;
end;
except
end;
Synchronize(Updt);
end;
procedure TPostThread.Updt;
begin
Form1.Memo2.Lines.Add(FMsg);
end;
end.Последний раз редактировалось NumLock, 16.12.2010 в 10:06. |