1

Тема: JScript: Эмуляция браузера

Приветствую, коллеги! Пытался осуществить авторизацию в мобильной версии сайта «В контакте», однако при втором использовании метода send возникает ошибка запрета доступа. Буду рад услышать комментарии:)

var CreateObject = function (ProgId) { return WScript.CreateObject(ProgId)};

var oXMLHTTP = CreateObject("MSXML2.XMLHTTP.6.0");//CreateObject("WinHttp.WinHttpRequest.5.1");//
var text;

oXMLHTTP.open ("GET", "http://m.vk.com/login", false);
oXMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
oXMLHTTP.send();
text = oXMLHTTP.responseText;

var link;

text.replace(/action = "[^"]+/, function (m) {link=m.split('"')[1]});

WScript.Echo("Получили линк на акшн формы. Теперь отправим туда наши мыло и пароль. «"+link+"»");

oXMLHTTP.open ("POST", link, false);
oXMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
oXMLHTTP.send("email=***@mail.ru&pass=***");
text = oXMLHTTP.responseText;
WScript.Echo(text);

2

Re: JScript: Эмуляция браузера

Внес исправления. Вместо MSXML2.XMLHTTP.6.0 начал использовать Msxml2.ServerXMLHTTP.6.0. Ошибка перестала появляться.

var CreateObject = function (ProgId) { return WScript.CreateObject(ProgId)};

var oXMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0");
var text;

oXMLHTTP.open ("GET", "http://m.vk.com/login", false);
oXMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
oXMLHTTP.send();
text = oXMLHTTP.responseText;

var link;

text.replace(/action = "[^"]+/, function (m) {link=m.split('"')[1]});

WScript.Echo("Получили линк на акшн формы. Теперь отправим туда наши мыло и пароль. «"+link+"»");

oXMLHTTP.open ("POST", link, false);
oXMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
oXMLHTTP.send("email=***@mail.ru&pass=***");
text = oXMLHTTP.responseText;
WScript.Echo(text);

Однако сервер отвечает так

Server: nginx/0.7.59
Date: Sat, 01 Oct 2011 13:27:44 GMT
Content-Type: text/html; charset=windows-1251
Connection: keep-alive
X-Powered-By: PHP/5.2.6-1+lenny3
Pragma: no-cache
Cache-control: no-store
P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
Location: http://vkontakte.ru/login?m=1&email=
Vary: Accept-Encoding
Content-Length: 0

Что не есть хорошо)

3

Re: JScript: Эмуляция браузера

Попробуйте вот так сделать:

param = "email=***@mail.ru&pass=***"
oXMLHTTP.open ("POST", link, false);
oXMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
oXMLHTTP.setRequestHeader ('Content-length', param.length );
oXMLHTTP.setRequestHeader ('Connection'   , 'close'); 

oXMLHTTP.send( param );

text = oXMLHTTP.responseText;
WScript.Echo(text);

У меня во "В Контакте" логина нету, проверить не могу, к сожалению.

4

Re: JScript: Эмуляция браузера

Решил переписать в виде объекта. Ошибок нет. Сделана поддержка редиректов, парсинга страницы, а также средства работы с формами.

Имеет всего три метода:
1. Navigate (GetOrPost, URL, Param, Callback),
2. SubmitForm (FormNameOrIndex, Values) // Values {param1:value1, param2:value2}
3. ParseDocument() возвращает объект document

Свойства:
1. Redirect (true по умолчанию) - флаг поддержки редиректа.
2. Response  - ответ сервера
3. ResponseHeaders  - заголовки в ответе сервера.
4. UserAgent (по умолчанию 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')

Spy00000, раза 3 сегодня получилось авторизоваться каким-то боком при использовании Вашей рекомендации. Однако сейчас опять проблема: пишет неправильный логин или пароль. Не понимаю в чем дело. Может быть в cookies?

var CreateObject = function (ProgId) { return WScript.CreateObject(ProgId)};

function Log(e)
{
	WScript.Echo(e);
}

function Browser()
{
	this.XMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0");
	this.Redirect = true;
	this.Response = null
	this.ResponseHeaders = null;
	this.Location = null;
	this.UserAgent = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1';
	this.__Document = CreateObject("HTMLFile");
}

Browser.prototype = 
{
	Navigate : function (GetOrPost, URL, Param, Callback)
	{
		if (URL.indexOf("://")!=-1) this.Location=URL; else
		{
			if (!this.Location) return;
			this.Location = this.Location.match(/(^\w+:\/\/[\w\.]+)\//)[1]+URL;
		}
		
		URL = this.Location;
		
		if (/:\/\//.test(URL)) 
	
		Log("Navigate\t"+URL);
	
		Callback = Callback || function (){}; 
		!Param? Param = null : "";
		GetOrPost = GetOrPost.toUpperCase();
		
		this.XMLHTTP.open(GetOrPost, URL, false);
		this.XMLHTTP.setRequestHeader ('User-agent', this.UserAgent);
		this.XMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
		this.XMLHTTP.setRequestHeader ("Accept", "text/html"); 
		if (GetOrPost=="POST") this.XMLHTTP.setRequestHeader ('Content-length', Param.length);
//		this.XMLHTTP.setRequestHeader ('Connection', 'close');
		this.XMLHTTP.send(GetOrPost=="POST"? Param : null);
		
		this.ResponseHeaders = this.XMLHTTP.getAllResponseHeaders();
		this.Response = this.XMLHTTP.responseText;
		
		Log([this.ResponseHeaders, this.Response].join("\n"));
//		Log("————————————————————————————————");
		Callback(this.ResponseHeaders, this.Response);
				
		if (this.Redirect)
		{
			var s="";
			if (this.ResponseHeaders && /Location: */.test(this.ResponseHeaders))
			{
				s=this.ResponseHeaders.match(/Location: *([^\n\r]+)/i)[1].toString();
				Log("Redirect to\t"+s);
				this.Navigate("GET", s, null, Callback);
			}
		}
	}, 
	
	ParseDocument : function ()
	{
		this.__Document.open();
		this.__Document.write(this.Response || "");
		this.__Document.close();
		return this.__Document;
	}, 
	
	SubmitForm : function (FormNameOrIndex, Values, Callback) // Values {param1:value1, param2:value2}
	{
		var DOM = this.ParseDocument();
		if (DOM.forms.length>0) 
		{
			var Form = DOM.forms[FormNameOrIndex];
			var InputElements = Form.getElementsByTagName('input');
			var Result=[];
			for (var i=0, l=InputElements.length; i<l; i++)
			if (InputElements[i].name && InputElements[i].name!="")
			Result.push(''+InputElements[i].name+'='+ InputElements[i].value);
			
			Result=Result.join("&");
			for (i in Values)
			{
				var re = new RegExp('(^|&)'+i+"=[^&]+","i")
				Result= Result.replace(re, '$1'+i+"="+Values[i]);
			}
			
			WB.Navigate(Form.method, Form.action, Result, Callback);
		}		
	}
}

function c(a,b)
{
	Log([a]);
}

var WB = new Browser();
	WB.Navigate("GET", "http://m.vk.com/");
	WB.SubmitForm(0, {email:"***@mail.ru", pass:"***"});
	WScript.Echo(WB.ParseDocument().body.innerText);

5

Re: JScript: Эмуляция браузера

JSman пишет:

Spy00000, раза 3 сегодня получилось авторизоваться каким-то боком при использовании Вашей рекомендации. Однако сейчас опять проблема: пишет неправильный логин или пароль. Не понимаю в чем дело. Может быть в cookies?

Так сразу не скажу, вариантов много слишком :) - cookies, referer, проверка на сервере на "а чего это вы больше 10 раз за минуту логинитесь" и т.д.
Надо отталкиваться от версии, которая работала и смотреть - насколько стабильно работает, и что поменялось.

По поводу setRequestHeader ('Content-length', Param.length) могу сказать вот что:
1. Описание, как правильно делать POST брал отсюда
2. Параметры на сервер передаются правильно, на это нареканий не было, НО(!!!) XHR у меня используется в FireFox, Opera и Chrome , в IE XHR не используется, так что могут быть проблемы специфичные для IE.

Что Вы пишете я не знаю, поэтому просто как вариант, если у Вас нет конкретной задачи сделать запрос именно через XHR, подумайте над таким алгоритмом:
1. Создать "HTMLFile",
2. Направить его на "http://m.vk.com/", дождаться, пока загрузится страница,
3. В форме на странице присвоить значения нужным элементам (email, pass),
4. сделать form.submit(), либо click() на нужной кнопке,
5. дождаться загрузки второй страницы.


И по коду Вашего объекта:
В SubmitForm вот в этом месте:


for (i in Values)
{
    var re = new RegExp(i+"[^&]+","i")
    Result= Result.replace(re, i+"="+Values[i]);
}

помоему, не совсем правильное регулярное выражение.
В текущем виде, если в Result будет параметр, к примеру, ...&first_email_address=asd@asd.com&... и Вашему объекту в SubmitForm передать Values = {email:"bnm@mail.ru"} , то &first_email_address=asd@asd.com& заменится на &first_email=bnm@mail.ru&, что совсем не правильно.

Имхо, правильней будет так:


for (i in Values)
{
    var re = new RegExp('(^|&)'+i+"=[^&]+","i")
    Result= Result.replace(re, '$1'+i+"="+Values[i]);
}

6

Re: JScript: Эмуляция браузера

Внес исправления.

Насколько я понимаю, пароль должен быть быть шифрован функцией encodeURIComponent.

Также есть иные ресурсы, на которых я проверяю правильность

    WB.Navigate("GET", "http://odnoklassniki.ru/", null, c);
    WB.SubmitForm(0, {"st.email":"***@mail.ru", "st.email":"***"}, c);
    
    WB.Navigate("GET", "http://m.mail.ru/cgi-bin/login?noclear=1&page=folders");
    WB.SubmitForm(0, {"Login":"***","Domain":"mail.ru", "Password":"***"});

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

7

Re: JScript: Эмуляция браузера

JSman пишет:

Насколько я понимаю, пароль должен быть быть шифрован функцией encodeURIComponent.

Может быть, но тогда скорее через encodeURIComponent должна проходить вся строка запроса. У себя я это с помощью JQuery через form.serialize() делал. Я с mail.ru гляну, что можно сделать, там у меня ящики есть.

8

Re: JScript: Эмуляция браузера

Кстати, для тестирования «браузера» написал вот такой вот веб-сервер:


var VB = new ActiveXObject("htmlfile").parentWindow;	
VB.document.write("<script language='VBScript'>Function GetData(Obj, data, num, bytTotal)\nObj.GetData data, num, bytTotal\nGetData = data\nEnd Function</script>");
var 
	Port = 9999,
	MainSocket = WScript.CreateObject("MSWinsock.Winsock.1","MainSocket_"),
	Sockets = {};
	MainSocket.LocalPort = Port;
	MainSocket.Listen();

var Host = this;

function MainSocket_ConnectionRequest(requestID)
{
	var NewSocket = WScript.CreateObject("MSWinsock.Winsock","Socket_");
	NewSocket.Accept(requestID);
	Sockets[NewSocket.SocketHandle]=NewSocket;
}

function Socket_SendComplete()
{
	delete Sockets[this.SocketHandle];
	this.Close();
	WScript.DisconnectObject(this);
}

function Socket_DataArrival(bytTotal)
{
  var Data = VB.GetData (this, Data, 8, bytTotal);
  this.SendData("HTTP/1.1 200 OK\n\n"+Data);
  return;
  }

while(1)WScript.Sleep(10);

Запускаем. Обращаемся к 9999 порту и получаем в ответе заголовки «браузера». Сейчас буду тестировать на сохранение кукисов. Может в этом дело.

9

Re: JScript: Эмуляция браузера

for (i in Values)
{
    var re = new RegExp('(^|&)'+i+"=[^&]+","i")
    Result= Result.replace(re, '$1'+i+"="+Values[i]);
}

Думаю, что корректней будет так:

for (i in Values)
            {
                var re = new RegExp('(^|&)'+i+"=[^&]*","i")
                Result= Result.replace(re, '$1'+encodeURIComponent(i)+"="+encodeURIComponent(Values[i]));
            }

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

И еще стало известно, что Cookie придется самому вручную прописывать.

10

Re: JScript: Эмуляция браузера

Добавил Referer, исправил мелкие ошибки. Осталось с Cookies разобраться и парсингом документа (предотвратить исполнение скриптов при парсинге HTML).

var CreateObject = function (ProgId) { return WScript.CreateObject(ProgId)};

function Log(e)
{
	WScript.Echo(e);
}

function Browser()
{
	this.XMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0");
	this.Redirect = true;
	this.Response = null;
	this.Referer = true;
	this.RefererString = null;
	this.ResponseHeaders = null;
	this.Location = null;
	this.UserAgent = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1';
	this.__Document = CreateObject("HTMLFile");
}

Browser.prototype = 
{
	Navigate : function (GetOrPost, URL, Param, Callback, RefererStr)
	{
		this.RefererString = RefererStr || this.Location;
	
		if (URL.indexOf("://")!=-1) this.Location=URL; else
		{
			if (!this.Location) return;
			this.Location = this.Location.match(/(^\w+:\/\/[\w\.]+)\//)[1]+URL;
		}
		
		URL = this.Location;
		
		if (/:\/\//.test(URL)) 
	
		Log("Navigate\t"+URL);
	
		Callback = Callback || function (){}; 
		!Param? Param = null : "";
		GetOrPost = GetOrPost.toUpperCase();
		
		this.XMLHTTP.open(GetOrPost, URL, false);
		this.XMLHTTP.setRequestHeader ('User-agent', this.UserAgent);
		this.XMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
		this.XMLHTTP.setRequestHeader ("Accept", "text/html"); 
		if (this.Referer && this.RefererString)
			this.XMLHTTP.setRequestHeader ("Referer", this.RefererString); 
		
		if (GetOrPost=="POST") 
		{
			this.XMLHTTP.setRequestHeader ('Content-length', Param.length);
			this.XMLHTTP.setRequestHeader ('Connection', 'close');
		}
		this.XMLHTTP.send(GetOrPost=="POST"? Param : null);
		
		this.ResponseHeaders = this.XMLHTTP.getAllResponseHeaders();
		this.Response = this.XMLHTTP.responseText;
		
		Log([this.ResponseHeaders, this.Response].join("\n"));
		Callback(this.ResponseHeaders, this.Response);
				
		if (this.Redirect)
		{
			var s="";
			if (this.ResponseHeaders && /Location: */.test(this.ResponseHeaders))
			{
				s=this.ResponseHeaders.match(/Location: *([^\n\r]+)/i)[1].toString();
				Log("Redirect to\t"+s);
				this.Navigate("GET", s, null, Callback);
			}
		}
	}, 
	
	ParseDocument : function ()
	{
		this.__Document.open();
		this.__Document.write(this.Response || "");
		this.__Document.close();
		return this.__Document;
	}, 
	
	SubmitForm : function (FormNameOrIndex, Values, Callback) // Values {param1:value1, param2:value2}
	{
		var DOM = this.ParseDocument();
		if (DOM.forms.length>0) 
		{
			var Form = DOM.forms[FormNameOrIndex];
			var InputElements = Form.getElementsByTagName('input');
			var Result=[];
			for (var i=0, l=InputElements.length; i<l; i++)
			if (InputElements[i].name && InputElements[i].name!="")
			Result.push(''+InputElements[i].name+'='+ InputElements[i].value);
			
			Result=Result.join("&");
			for (i in Values)
			{
				var re = new RegExp('(^|&)'+i+"=[^&]+","i")
				Result= Result.replace(re, '$1'+encodeURIComponent(i)+"="+encodeURIComponent(Values[i]));
			}
			
			WB.Navigate(Form.method, Form.action, Result, Callback);
		}		
	}
}

function c(a,b)
{
	Log([a, b]);
}

var WB = new Browser();
	WB.Navigate("GET", "http://m.vk.com/", null, c);
	WB.SubmitForm(0, {email:"***@mail.ru", pass:"***"}, c);

	WScript.Echo(WB.ParseDocument().body.innerText);

//	WB.Navigate("GET", "http://odnoklassniki.ru/", null, c);
//	WB.SubmitForm(0, {"st.email":"***@mail.ru", "st.email":"***"}, c);
	
//	WB.Navigate("GET", "http://m.mail.ru/cgi-bin/login?noclear=1&page=folders");
//	WB.SubmitForm(0, {"Login":"***","Domain":"mail.ru", "Password":"***"});

	WB.Navigate("GET", "http://localhost:9999");
	WB.Navigate("POST", "http://localhost:9999", encodeURI("Login=jsman@m.ru&Password=йцукен"));


//	WB.Navigate("GET", "http://internet.yandex.ru/");
	
	WScript.Echo(WB.ParseDocument().body.innerText);

11

Re: JScript: Эмуляция браузера

2 JSman:

JSman пишет:

предотвратить исполнение скриптов при парсинге HTML

Как вариант - присвоить содержимого через document.body.innerHTML. Это позволяет избежать выполнения скриптов. Вроде бы.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

12

Re: JScript: Эмуляция браузера

Xameleon, точно позволяет! Спасибо. Проверил  такой скрипт

var h = WScript.CreateObject("HTMLFile");
h.open();
h.close();

h.body.innerHTML = "<span>123</span><script language=\"javascript\">alert(2)</script>";
WScript.Echo(h.body.innerHTML);

13

Re: JScript: Эмуляция браузера

Внесены исправления. Теперь перед Вами полностью рабочий код:)

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

Объект Browser

Имеет всего четыре метода:
1. Navigate (GetOrPost, URL, Param, Callback)
       GetOrPost — обязательный параметр — принимает значения get или post
       URL — обязательный параметр — интернет-ресурс
       Param — обязательный параметр при post запросах
       Callback — необязательный параметр — ссылка на функцию, которая будет вызвана сразу же после ответа сервера (и до редиректа). Функция будет вызвана с тремя параметрами status, ResponseHeaders, Response.
2. SubmitForm (FormNameOrIndex, Values, Callback) — ввести данные в форму и отправить
       FormNameOrIndex — имя формы либо ее порядковый номер (с нуля).
       Value — обязательный параметр — объект со с заданными свойствами по заполнению формы: {param1:value1, param2:value2}
3. ParseDocument() возвращает объект document.
4. ClearCookies() - очистка кукисов.

Свойства:
1.     Redirect (true по умолчанию) - флаг поддержки редиректа.
2.    Response  - ответ сервера
3.    ResponseHeaders  - заголовки в ответе сервера.
4.    UserAgent (по умолчанию 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')
5.    RefererString — URL реферера
6.     Location — текущий URL
7.     Cookie — флаг поддержки кукисов. (true по умолчанию)

Код:

var CreateObject = function (ProgId) { return WScript.CreateObject(ProgId)};

function Log(e)
{
//	  WScript.Echo(e);
return e;
}

function Browser()
{
	this.XMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0");
	this.Redirect = true;
	this.Response = null;
	this.Referer = true;
	this.RefererString = null;
	this.ResponseHeaders = null;
	this.Location = null;
	this.__CookieStorage = " ";
	this.UserAgent = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1';
	this.__Document = CreateObject("HTMLFile");
	this.Cookie = true;
}

Browser.prototype = 
{
	__ParseCookie : function (m, cookie)
	{
		if (!this.__CookieStorage) this.__CookieStorage =" ";
		this.__CookieStorage+=" "+cookie+";";
		Log("Cookie Storage:\t"+this.__CookieStorage);
	},
	
	ClearCookies : function ()
	{
		this.__CookieStorage=" ";
	},

	Navigate : function (GetOrPost, URL, Param, Callback, RefererStr)
	{
		this.RefererString = RefererStr || this.Location;
	
		if (URL.indexOf("://")!=-1) this.Location=URL; else
		{
			if (!this.Location) return;
			this.Location = this.Location.match(/(^\w+:\/\/[\w\.]+)\//)[1]+URL;
		}
		
		URL = this.Location;
		
		if (/:\/\//.test(URL)) 
	
		Log("Navigate\t"+URL);
	
		Callback = Callback || function (){}; 
		!Param? Param = null : "";
		GetOrPost = GetOrPost.toUpperCase();
		
		this.XMLHTTP.open(GetOrPost, URL, false);
		this.XMLHTTP.setRequestHeader ('User-agent', this.UserAgent);
		this.XMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
		this.XMLHTTP.setRequestHeader ("Accept", "text/html"); 
		if (this.Referer && this.RefererString)
			this.XMLHTTP.setRequestHeader ("HTTP_REFERER", this.RefererString); //this.RefererString
		
		if (GetOrPost=="POST") 
		{
			this.XMLHTTP.setRequestHeader ('Content-length', (!Param?"":Param).length);
			this.XMLHTTP.setRequestHeader ('Connection', 'close');
		}

		if (this.Cookie && this.__CookieStorage!=" ")
		{
			this.XMLHTTP.setRequestHeader ("Cookie", this.__CookieStorage);
		}

		this.XMLHTTP.send(GetOrPost=="POST"? Param : null);
				
		this.ResponseHeaders = this.XMLHTTP.getAllResponseHeaders();
		this.Response = this.XMLHTTP.responseText;

		if (this.Cookie)
		{
			this.ResponseHeaders.replace(/^Set-Cookie *: *([^;]+)/igm, function( obj ){ return function (m, cookie){ obj.__ParseCookie(m, cookie) } }(this));
		}

		Log(["Response status:\t"+this.XMLHTTP.status, "\n\nResponseHeaders:\n\n"+this.ResponseHeaders, "\n\nResponse:\n\n"+this.Response]);
		Callback(this.XMLHTTP.status, this.ResponseHeaders, this.Response);
		
		if (this.Redirect)
		{
			var s="";
			if (this.ResponseHeaders && /^Location: */im.test(this.ResponseHeaders))
			{
				s=this.ResponseHeaders.match(/^Location: *([^\n\r]+)/im)[1].toString();
				Log("Redirect to\t"+s);
				this.Navigate("GET", s, null, Callback);
			}
		}
	}, 
	
	ParseDocument : function ()
	{
		var Code = (this.Response || "").replace(/<script([^>]*)/, "<script type=\"text/plain\"");
		this.__Document.open();
		this.__Document.write(Code);
		this.__Document.close();
		return this.__Document;
	}, 
	
	SubmitForm : function (FormNameOrIndex, Values, Callback) // Values {param1:value1, param2:value2}
	{
		var DOM = this.ParseDocument();
		if (DOM.forms.length>0) 
		{
			var Form = DOM.forms[FormNameOrIndex];
			var InputElements = Form.getElementsByTagName('input');
			var Result=[];
			for (var i=0, l=InputElements.length; i<l; i++)
			if (InputElements[i].name && InputElements[i].name!="")
			Result.push(''+InputElements[i].name+'='+ InputElements[i].value);
			
			Result=Result.join("&");
			for (i in Values)
			{
				var re = new RegExp('(^|&)'+i+"=[^&]*","i")
				Result= Result.replace(re, '$1'+encodeURIComponent(i)+"="+encodeURIComponent(Values[i]));
				
				if (!re.test(Result)) Result+="&"+encodeURIComponent(i)+"="+encodeURIComponent(Values[i]);
			}
			
			Log("Serialized Form Data:\t"+Result);
			this.Navigate(Form.method, Form.action, Result, Callback);
		}		
	}
}

Использование:



function callback(a,b,c)
{
	WScript.Echo([a, b, c]);
}

var WB = new Browser();

	WB.Navigate("GET", "http://m.mail.ru/cgi-bin/login?noclear=1&page=folders");
	WB.SubmitForm(0, {"Login":"***","Domain":"mail.ru", "Password":"***"});

//	WB.Navigate("GET", "http://mail.ru/");
//	WB.SubmitForm(1, {"Login":"***","Domain":"mail.ru", "Password":"***"});


//	WB.Navigate("GET", "http://vk.com/", null, callback);
//	WB.SubmitForm(0, {email:"***@mail.ru", pass:"***"}, callback);
//	WB.Navigate("GET", "http://vk.com/", null, callback);

	WScript.Echo(WB.ParseDocument().body.innerText);

14

Re: JScript: Эмуляция браузера

Пример ниже у меня так и не завершился:


var WB = new Browser();
WB.Navigate('GET', 'http://ya.ru/');

var resp = WB.ParseDocument().body.innerHTML;
WScript.Echo(resp);

Наблюдаются какие-то проблемы с внутренними редиректами.

( 2 * b ) || ! ( 2 * b )

15

Re: JScript: Эмуляция браузера

Rumata, спасибо! Поправил:)

16 (изменено: Rumata, 2011-10-08 00:17:21)

Re: JScript: Эмуляция браузера

JSman
Еще заметил такую вещь. Ваш Browser не может "пробиться" через прокси-сервер. А как задать явно параметры прокси-сервера в заголовках запроса я не помню, да и разбираться было некогда. Кстати у меня вопрос - чем был вызвана необходимость использовать объект Msxml2.ServerXMLHTTP вместо обычного Msxml2.XMLHTTP, который прокси видит (видимо из настроек браузера)?

Следующий код прекрасно работает как с прокси так и без него.

var url = 'http://ya.ru/';

var xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
xmlhttp.open('GET', url, false);

xmlhttp.send();

var resp = xmlhttp.responseText;
WScript.Echo(resp);
( 2 * b ) || ! ( 2 * b )

17

Re: JScript: Эмуляция браузера

Rumata пишет:

Чем был вызвана необходимость использовать объект Msxml2.ServerXMLHTTP

Компонент Msxml2.XMLHTTP мне выдавал ошибку при ответе сервера со статусом 200 и длиной ответа в 0, также были постоянные ошибки в отношении отказа в доступе и непонятные ошибки при вызове метода send.

Rumata, что касается проблемы прокси — я в курсе и пока считаю это проблемой второго плана, так как  сейчас больше всего интересует правильность реализации эмуляции (в особенности куки). Хотя авторизоваться у меня получилось во всех тестируемых сервисах.

П.С. Если все это получится запустить в рамках Msxml2.XMLHTTP, то это будет победа:)

18

Re: JScript: Эмуляция браузера

Теперь включена поддержка Windows 7:-)

function Log(e)
{
//    LogFile.WriteLine(e);  
    //WScript.Echo(e);
return e;
}


function Browser()
{
    this.XMLHTTP = CreateObject("Msxml2.ServerXMLHTTP.6.0");
    this.Redirect = true;
    this.Response = null;
    this.Referer = true;
    this.RefererString = null;
    this.ResponseHeaders = null;
    this.Location = null;
    this.__CookieStorage = " ";
    this.UserAgent = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1';
    this.__Document = CreateObject("HTMLFile");
    this.Cookie = true;
    this.Status = 0;
}

Browser.prototype = 
{
    __ParseCookie : function (m, cookie)
    {
        if (!this.__CookieStorage) this.__CookieStorage =" ";
        this.__CookieStorage+=" "+cookie+";";
//        Log("Cookie Storage:\t"+this.__CookieStorage);
    },
    
    ClearCookies : function ()
    {
        this.__CookieStorage=" ";
    },

    Navigate : function (GetOrPost, URL, Param, Callback, RefererStr)
    {
        WScript.Sleep(300);
        this.RefererString = RefererStr || this.Location;
    
        if (URL.indexOf("://")!=-1) this.Location=URL; else
        {
            if (!this.Location) return;
            this.Location = this.Location.match(/(^\w+:\/\/[\w\.]+)\//)[1]+URL;
        }
        
        URL = this.Location;
        
        if (/:\/\//.test(URL)) 
        Log("Navigate\t"+URL);
    
        Callback = Callback || function (){}; 
        !Param? Param = null : "";
        GetOrPost = GetOrPost.toUpperCase();
        
        this.XMLHTTP.open(GetOrPost, URL, false);
        this.XMLHTTP.setRequestHeader ('User-agent', this.UserAgent);
        this.XMLHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded"); 
        this.XMLHTTP.setRequestHeader ("Accept", "text/html"); 
        if (this.Referer && this.RefererString)
            this.XMLHTTP.setRequestHeader ("HTTP_REFERER", this.RefererString); //this.RefererString
        
        if (GetOrPost=="POST") 
        {
            this.XMLHTTP.setRequestHeader ('Content-length', (!Param?"":Param).length);
            this.XMLHTTP.setRequestHeader ('Connection', 'close');
        }
        
        this.XMLHTTP.setRequestHeader ("Cookie", "test");
        
        if (this.Cookie && this.__CookieStorage!=" ")
        {
            this.XMLHTTP.setRequestHeader ("Cookie", this.__CookieStorage);
        }

    var e;
        try {
            this.XMLHTTP.send(GetOrPost=="POST"? Param : null);
            this.Status = this.XMLHTTP.status;
        } catch (e) {this.Status = 302;}
        
        this.ResponseHeaders = this.XMLHTTP.getAllResponseHeaders();

        try {this.Response = this.XMLHTTP.responseText;} catch (e) {this.Response="";};

        if (this.Cookie)
        {
            this.ResponseHeaders.replace(/^Set-Cookie *: *([^;]+)/igm, function( obj ){ return function (m, cookie){ obj.__ParseCookie(m, cookie) } }(this));
        }

        Log(["Response status:\t"+this.Status, "\n\nResponseHeaders:\n\n"+this.ResponseHeaders, "\n\nResponse:\n\n"+this.Response]);
        Callback(this.Status, this.ResponseHeaders, this.Response);
        
        if (this.Redirect)
        {
            var s="";
            if (this.ResponseHeaders && /^Location: */im.test(this.ResponseHeaders))
            {
                s=this.ResponseHeaders.match(/^Location: *([^\n\r]+)/im)[1].toString();
                Log("Redirect to\t"+s);
                this.Navigate("GET", s, null, Callback);
            }
        }
    }, 
    
    ParseDocument : function ()
    {
        var Code = (this.Response || "").replace(/<script([^>]*)/, "<script type=\"text/plain\"");
        this.__Document.open();
        this.__Document.write(Code);
        this.__Document.close();
        return this.__Document;
    }, 
    
    SubmitForm : function (FormNameOrIndex, Values, Callback) // Values {param1:value1, param2:value2}
    {
        var DOM = this.ParseDocument();
        if (DOM.forms.length>0) 
        {
            var Form = DOM.forms[FormNameOrIndex];
            var InputElements = Form.getElementsByTagName('input');
            var Result=[];
            for (var i=0, l=InputElements.length; i<l; i++)
            if (InputElements[i].name && InputElements[i].name!="")
            Result.push(''+InputElements[i].name+'='+ InputElements[i].value);
            
            Result=Result.join("&");
            for (i in Values)
            {
                var re = new RegExp('(^|&)'+i+"=[^&]*","i")
                Result= Result.replace(re, '$1'+encodeURIComponent(i)+"="+encodeURIComponent(Values[i]));
                
                if (!re.test(Result)) Result+="&"+encodeURIComponent(i)+"="+encodeURIComponent(Values[i]);
            }
            
//            Log("Serialized Form Data:\t"+Result);
            this.Navigate(Form.method, Form.action, Result, Callback);
        }        
    }
}

Остается подкорректировать метод SubmitForm, так как мне лень его было писать)

19

Re: JScript: Эмуляция браузера

JSman пишет:

Теперь включена поддержка Windows 7:-)

А что такого специфического в семерке? Сравнил два последних кода и не понял. Из существенных изменений только две обертки try/catch при получении статуса и тела отклика. Веселые ребята из Рэдмонда опять что-то накрутили для повышения несовместимости кода?

( 2 * b ) || ! ( 2 * b )

20

Re: JScript: Эмуляция браузера

Вот именно, что накрутили. При получении пустого Response со статусом 302 все дружно падает:-)

21

Re: JScript: Эмуляция браузера

Мне эта тема интересна, поэтому "придираюсь", в хорошем смысле этого слова. Есть свои наработки, но пока не все так гладко как хотелось бы.

При получении пустого Response со статусом 302 все дружно падает

Вопрос в другом. Может не стоит читать отклик при статусе отличном, например, от 2xx? Или, еще лучше, отдать результат "на растерзание" пользовательской функции:


navigate: function(url, options)
{
    var result;
...
    this.xmlhttp = new ActiveXObject('Msxml2.ServerXMLHTTP');
    this.xmlhttp.onreadystatechange = function()
    {
        var result = options.onreadystatechange(this.xmlhttp);
    };
    this.xmlhttp.open(options.method, url, options.async);
...
}

.
Эта тема очень кстати! Msxml2.XMLHTTP не понимает внутренние/внешние перенаправления клиента. Это просто бардак какой-то. Когда-то я написал примерно такой код (см. ниже). Который работает совершенно по разному на разных тестированных машинах -- XP Sp3, Vista Sp2. В одном случае не работают внешние редиректы (что можно понять), но работают внутренние, в другом случае редиректы не работают вообще. С Msxml2.ServerXMLHTTP все работает. Хотя в этой ОС никогда не будешь уверен в чем-то до конца.


// внешние редиректы на субдомены вида *.yandex.ru
var url = 'http://yandex.ru';

// внутренние редиректы на другую страницу в этом же домене
var url = 'http://www.ru';

var xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');

xmlhttp.onreadystatechange = function()
{
	WScript.Echo('=============');
	WScript.Echo(xmlhttp.readyState);
	if ( xmlhttp.readyState != 4 ) {
		return;
	}
	WScript.Echo(xmlhttp.status);
	WScript.Echo(xmlhttp.responseText.length);
	WScript.Echo(xmlhttp.getAllResponseHeaders());
};

xmlhttp.open('GET', url, false);
xmlhttp.send();
( 2 * b ) || ! ( 2 * b )

22

Re: JScript: Эмуляция браузера

Rumata пишет:

Может не стоит читать отклик при статусе отличном, например, от 2xx? Или, еще лучше, отдать результат "на растерзание" пользовательской функции

И да, и нет. Возвращать в любом случае надо, так как во время редиректа могут выводиться важные сообщения. У меня в реализации при флаге Redirect=true в заголовке ответа отыскивается Location и происходит вызов Navigate вновь с новым параметром. При этом если вы указали callback, то в этом случае callback передается «по наследованию» в случае редиректа. Также во время вызова callback можно предотвратить нежелательный редирект, присвоив false свойству Redirect.

23

Re: JScript: Эмуляция браузера

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

С одной стороны XMLHTTP не справляется с редиректами, но прозрачно работает с куками - я спокойно авторизуюсь методом POST на сайте своего провайдера, затем методом GET читаю страницу с информацией текущего суммарного трафика.

С другой стороны - ServerXMLHTTP предоставляет гибкость в работе с протоколами, но при этом вся работа для успешной авторизации (например, передача куков при редиректе) должна быть выполнена вручную.

( 2 * b ) || ! ( 2 * b )

24

Re: JScript: Эмуляция браузера

2 Rumata: Делаем вывод - для получения универсального варианта можно использовать компонент с гибкой работой с протоколами и приделать к нему обработчик куков . Честно говоря - я отказался и от XmlHTTP и от ServerXmlHTTP и пользуюсь WinHttpRequest. У него самый богатый функционал, на мой взгляд. ) Удобство установки User-Agent, настройка включения и выключения автоматических редиректов по HTTP и с HTTP на HTTPS и обратно. ) Вот на счёт работы с куками - вопрос сложный. Вчера дособирал качалку музыки из контакта в виде сайта. Так вот на халявном хосте он почему то с куками сам не работает, а вот на локальном компе без проблем. Есть подозрения, что он куки при этом пытается писать куда нить на хард, а прав ему не хватает. ) А в остальном шикарный объект.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

25 (изменено: Rumata, 2011-10-19 13:20:12)

Re: JScript: Эмуляция браузера

Простите, я сегодня желчный и сварливый, но, по-моему, хрен редьки не слаще

Читаю эти страницы
XMLHttpRequest
ServerXMLHttpRequest
WinHttpRequest

WinHttpRequest это вообще какое-то недоразумение - поддержка только HTTPS? протоколов, нет поддержки FTP, отсутствует onreadystatechange, но вместо него ввели какие-то OnError/OnResponseDataAvailable/OnResponseFinished/OnResponseStart, которые установить нельзя


var url = 'http://localhost';
//var url = 'ftp://localhost';

var WinHttpReq = new ActiveXObject('WinHttp.WinHttpRequest.5.1');

//WinHttpReq.OnError = function() {};
//WinHttpReq.OnResponseDataAvailable = function() {};
//WinHttpReq.OnResponseFinished = function() {};
//WinHttpReq.OnResponseStart = function() {};

WinHttpReq.Open('GET', url, false);
WinHttpReq.Send(); 
WScript.Echo(WinHttpReq.Status, WinHttpReq.StatusText, WinHttpReq.ResponseText.length);

Расскоментируйте любую строку вида WinHttpReq.On и увидите сообщение вида:

Microsoft JScript runtime error: Object doesn't support this property or method

Измените протокол HTTP на FTP и получите сообщение вида

WinHttp.WinHttpRequest: The URL does not use a recognized protocol

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

( 2 * b ) || ! ( 2 * b )

26

Re: JScript: Эмуляция браузера

2 Rumata: Быть желчным и сварливым точно лишнее. ) А вот читать ВДУМЧИВО документацию очень даже стоит. Объект работает и с HTTP и c HTTPS и даже авторизуется по сертификатам. ) И умеет много чего ещё. ) Коллега, если Вам интересно подискутировать на тему его удобства - я с радостью (абсолютно честно) буду рад поделиться с Вами всей информацией которой владею. )

На счёт On... это не свойства это COM события. )


Dim WithEvents WinHttpRequest As WinHttp.WinHttpRequest

Private Sub WinHttpRequest_OnError(ByVal ErrorNumber As Long, ByVal ErrorDescription As String)

End Sub

Private Sub WinHttpRequest_OnResponseDataAvailable(Data() As Byte)

End Sub

Private Sub WinHttpRequest_OnResponseFinished()

End Sub

Private Sub WinHttpRequest_OnResponseStart(ByVal Status As Long, ByVal ContentType As String)

End Sub

В VBS / JS они к сожалению не подключаются. Поэтому для асинхронной обработки юзается метод WaitForResponse(Timeout).

Но об это лично и в ICQ. Не хочу я форум засорять.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

27

Re: JScript: Эмуляция браузера

OFF: to Rumata: Ну вот. И забросили тему. А я так надеялся поделиться опытом и подчерпнуть от Вас новых знаний. )

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

28

Re: JScript: Эмуляция браузера

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

( 2 * b ) || ! ( 2 * b )

29 (изменено: mikser, 2011-11-02 21:40:54)

Re: JScript: Эмуляция браузера

Кароче все это конечно хорошо но, возникают либо проблемы с редиректами, либо с куками, либо с проксями, либо не возможно замутить асинхронный запрос, либо все упирается в баги https реализации от Майкрософт (из за этого отпадает WinHttp.WinHttpRequest) .

Выхода  я вижу 4:
1. реализовать свой собственный ActiveX для https запросов.
2. с помошью врапера подцепить какуюнить dll'ку, в которой есть возможность использовать делать https запросы и поддержка асинхроного режима.
3. попробовать использовать .NET.
4. реализовать через сокеты, но тут будут трудности с HTTPS'ом .

PS если кто нить надоумит меня как сделать запрос через врапер, используя winapi - WinHTTP (не COM), буду очень признателен.

30

Re: JScript: Эмуляция браузера

2 mikser: Хм, а позвольте поинтересоваться, что у Вас за "баги" возникают ? У меня всё прекрасно работает. И редиректы и HTTPS. И cookies. ) Может быть стоит разобраться более точно в проблеме ? Хотелось бы взглянуть на код. Я например на этом объекте собрал целый сайт для скачки музыки из vkontakte.ru. А там и HTTPS и кукисы и редиректы ) Всё сразу. И всё работает. В личку или по ICQ готов даже ссылкой поделиться.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

31 (изменено: mikser, 2011-11-02 22:13:14)

Re: JScript: Эмуляция браузера

Баги там скрытые, код 100 раз перепроверял, все там правильно.
Писал регистратор, там есть запросы через web прокси по https протоколу.
Алгоритм там зациклен: сначала регится первый аккаунт, он как нистранно региструрется успешно.
Потом второй - по тому же алгоритму, и тут всплывает исключение - "этот файл уже используется", какой файл, причем тут файл, у меня все в оперативке происходит, в скрипте не содержится функций которые что либо записывали на диск.
Try Catch не спасли, упростить код что бы выловить баг у меня не получилось.
Я так понял все запросы этот актив икс от майкрософта сохраняет где то в кеше, но по какой-то причине в случае использования прокси, с отключенными редиректами и только по протоколу https  второй одинаковый запрос вызывает перезапись закешированого файла, но этот файл еще почемуто то, где то используется (и еще запросы должены быть асинхроными).

Почему я уверен что это баг Майкрософта, а не мой?
Просто мне стало интересно что это за чертовщина и я использовал запрещенный прием .
Нагуглил альтернативный https activex модуль, но он разумеется оказался платным - 300$ - 500$ пришлось крякать .
Переписал свое приложение под этот модуль, а  winhttprequest вообще не использовал, грубо говоря просто заменил вызовы виндового модуля вызовами стороннего, и все стало работать как надо! В логике скрипта ошибок не было, к сожалению добавились другие глюки вызваные видимо кривым кряком... Полученный скрипт уже можно было использовать, но он работал не стабильно.
Вот теперь ищу альтернативные пути.

32

Re: JScript: Эмуляция браузера

2 mikser: А это как раз куки и кэш сохранялись в файл. ) Так что всё логично. ) Я не просто так прошу код показать. Ну не хотите как хотите ) Но тогда и не зачем на компонент ругаться. Любым инструментом нужно уметь пользоваться.

Рекомендую Вам обратить внимание на свойство Option у WinHttpRequest для тонких настроек. Оно решает ОЧЕНЬ многие проблемы. )
http://msdn.microsoft.com/en-us/library … s.85).aspx

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

33 (изменено: mikser, 2011-11-02 22:19:21)

Re: JScript: Эмуляция браузера

Вполне возможно, у меня там свой движок кукисов. Как бы их отключить, что бы winhttprequest не писал их ни куда ?

34

Re: JScript: Эмуляция браузера

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

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

35

Re: JScript: Эмуляция браузера

Экземпляры тоже не спасают. Всеравно вылазит таже ошибка.

36

Re: JScript: Эмуляция браузера

Пока КОД не увижу - смысла обсуждения нет. ) Если не хотите выкладывать на форум - прошу в ICQ (252505765). А то это похоже на проведение операции больному на мозжечёк с перепиской по почте. ) Лечить надо на месте.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

37 (изменено: mikser, 2011-11-03 04:57:32)

Re: JScript: Эмуляция браузера

Xameleon, да действительно ошибка в коде была у меня: накапливались заголовки Referer.
Из за этого второй запрос был вида:
Referer: A
Referer: B
то есть в одном запросе сразу два реферала.
Однако какое замечательное описание для этой ошибки:

ошибка №-2147024713: Невозможно создать файл, так как он уже существует.

Читаешь и сразу понимаешь где накосячил.

ИМХО: Не коректный запрос к серверу не должен приводить к сбою на стороне клиента.

38

Re: JScript: Эмуляция браузера

OFF: Человеческий фактор. Всё бывает.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

39 (изменено: mikser, 2011-11-08 14:45:03)

Re: JScript: Эмуляция браузера

Может подскажет кто-нить простенький желательно на чистом js html2json скрипт с поддержкой CSS like запросов типа:

div>span.headers[0]

40

Re: JScript: Эмуляция браузера

Эта штука называется CSS Selectors. Функции использования селекторов есть в распространенных фреймворках типа base2.js, jquery, mootools. Можете погуглить, найдете Css Selectors от Dean Edwards. Если будут еще вопросы, создайте отдельную тему.

41 (изменено: mikser, 2011-11-20 15:36:55)

Re: JScript: Эмуляция браузера

JSman У него нужный узел ищется по дом дереву, а не по голому HTML.
Я тут посмотрел вашь навигатор, ему не хватает нормального обработчика куков тот, что есть высылает всегда одинаковые куки на все URL, не обрабатывает флаги Expires, параметы secure и path, не эскейпит опасные символы.

А вот мой движок куков, но он работает только в HTA из за методов decodeURIComponent, encodeURI.


var UND="undefined";
function isUnd(a)
{return typeof a ==UND}

var CookieEngine={
Cookies:{
/*
"domain.com":{
		"/path":
				{
					"name":{value:"",expires:"",secure:""}
				}
		}
*/
},

parseURL:function(url)//ret {d:"domen.ru",p:"/path"}
	{
			//http://yandex.ru/dir/index.html
			//http(s?):\/\/([^\/:]+)(?::(\d+))?((?:(?:\/[\d\wа-я._-]*)*)\/)?
		if (/http(s?):\/\/([^\/?:]+)(?::(\d+))?((?:\/[\wа-я.=_-]*)*)/i.test(url))
		{
			return {s: (RegExp.$1 ? true : false), port:( RegExp.$3 ? RegExp.$3 : (RegExp.$1 ? 443 : 80) ) ,d: "." + RegExp.$2, p: RegExp.$4 || "/"}
		}
		return null;
	},
DelCookie:function(name, path, domain)
	{
	 if (isUnd(name)  ||
		 isUnd(path)  ||
		 isUnd(domain) )
		 return null;
	 else delete this.Cookies[domain][path][name];
	 return this;
	},
GetCookie:function(name, path, domain)
	{
	 if (isUnd(name)  ||
		 isUnd(path)  ||
		 isUnd(domain)||
		 isUnd(this.Cookies[domain]) ||
		 isUnd(this.Cookies[domain][path]) ||
		 isUnd(this.Cookies[domain][path][name]) )
		 return "";
		var coo=this.Cookies[domain][path][name];
	    var now=new Date();
		now.setMinutes(now.getMinutes()+now.getTimezoneOffset())
		if(now > coo.expires && coo.expires!=1) //устарела и не текущая сесия
		{
				this.DelCookie(name, path ,domain)
				return "";
		}
		
		return coo.value;
	},
SetCookie:function(name, value, path, domain, expires, secure)
	{
		 if(isUnd(name)||
			isUnd(path) ||
			isUnd(domain))
			 return null;
		 if (typeof expires=="string")
		 {
		   //Fri, 18-Mar-2011 20:32:35 GMT
		   //Mon, 01-Jan-1990 00:00:00 GMT
		   //Thu, 31-Dec-37 23:55:55 GM
			expires	= expires.replace(/-/g," ").replace(/([a-zA-Z]{3} )(\d{1,3}) /i,
				function(c,b,a){
				  var L=a.length;	
				  return b + (L==3 ? "2" : (L==2 ? "20":"200")) + a + " ";
				} );//тут нада поработать над парсингом даты
			//log("@@expires: "+expires)
			expires=new Date(expires)
		 }
		 else if( !(expires.getDate)) //не время
		 {
			 expires=1;//текущая сессия

		 }//else expires имеет тип дейт
		 
		 secure=secure ? true : false;
		 if (!this.Cookies[domain])
			this.Cookies[domain]={};
		 if (!this.Cookies[domain][path])
			this.Cookies[domain][path]={};

		 this.Cookies[domain][path][name]={"value":value, "expires": expires ,"secure": secure}
		 return this;

	},
Clear:function( domen, path)
	{
		if (!isUnd(domen))
		{
			if (!isUnd(path))
			{
				delete this.Cookies[domen][path]
			}
			else{ delete this.Cookies[domen]}
		}
		else this.Cookies={};
		return this;
	},
parseSetCookie:function(url,s)//парсит одну сет куку
	{
		if (isUnd(s) || isUnd(url) || !(url=this.parseURL(url)))
		{
			return this;	
		}
		var coo={
				domain:	 url.d,
				path:	 url.p,
				secure:	 false,
				expires: 1 //1 - значит хранить до конца текущей сесии
				};//coo
		s=s.split(/;\s*/);
		var nv = s[0].split(/\s*=\s*/);
		var name = decodeURIComponent(nv[0]);
		var value = decodeURIComponent(nv[1]);
		for (var i=1;i<s.length;i++)
		{
			nv=s[i].split(/\s*=\s*/)
			var cn=decodeURIComponent(nv[0].toLowerCase())
			coo[cn]= (typeof nv[1] != UND )? decodeURIComponent(nv[1]) : true;
		}//for
		//L("<hr><pre> url = "+Dumper(url)+"<\/pre><pre> coo="+Dumper(coo)+"<\/pre>")
		//ToDo: добавить проверку  Что coo.domain == url.d или coo.domain есть поддомен url.d
		this.SetCookie(name, value, coo.path, coo.domain, coo.expires, coo.secure);//name, value, path, domain, expires, secure

		return this;
	},
toHttpHeader:function(u)//u = url //ret String
	{
		if (!isUnd(u))
		{
			u=this.parseURL(u);//ret {d:"doem",p:"path"}
		}
		else return "";//ошибка не задан урл
		var r="",v;
		//var d=this.Cookie[u.d];
        for (var d in this.Cookies)
        {  //0123456789
		   //www.aa.com
		   //    aa.com
		   //L(d)
		   var Li=u.d.lastIndexOf(d);
		   if (Li > -1 && Li+d.length==u.d.length)
		   {//L(d)
			for (var p in this.Cookies[d])
			 {//L(p)
				if (u.p.indexOf(p)==0)//есть совпадение пути
				{//L(p)
					for (var n in this.Cookies[d][p])
					{//L(n)
						if (v=this.GetCookie(n, p, d))
						{//L(v)
							r+= ( r.length > 0 ? "; " : "" )+ n+"="+encodeURI(v)
						}//if
					}//for
				}//if
			 }//for
		   }//if
        }//for
	     return r;
	}//httpheader


}//cookieman

function CookieManager()
{
	//return this;
}

CookieManager.prototype=CookieEngine;

Пример


 <head>
  <title>Тестим куки менеджер</title>
	<script type="text/javascript"  charset="utf8" src="CookieManager.js"></script>
 </head>

 <body>
  <h1>Тестим куки менеджер</h1>
  <script type="text/javascript">
    function L(t){document.write("<pre>"+t+"<\/pre>")}

	var url="https://ya.ru/doom/page.html?aasd=21321"
	var coo="email=papa@ya.ru; domain=ya.ru; path=/doom/page.html; expires=Fri, 18-Mar-2012 20:32:35 GMT; "
	var C=new CookieManager()
	L("["+C.toHttpHeader(url)+"]")
	C.parseSetCookie(url,coo)

	L("[ "+"https://ya.ru/" +" : "+C.toHttpHeader("https://ya.ru/")+"]")
	L("[ "+url +" : "+C.toHttpHeader(url)+"]")
 
  </script>
 </body>