Начнем Потребовалось точно узнать что за браузер использует пользователь . Тк способ с HTTP_USER_AGENT не является стопроцентным надо было найти другое решение. После ковыряния интернета в поисках нужной информации , наткнулся на соответсвующий док от mozilla dev team http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html , но к сожалению они наивно верят что браузер можно точно определить используя navigator.userAgent; , поэтому я прибег к другому выходу - нашел различия в обработке js и результат перед вами - скрипт точно обрабатывает движки на Gecko ( Firefox,Netscape,Mozilla) , Оперу и ИЕ. PHP: function out(value) { document.getElementById("result").innerHTML = document.getElementById("result").innerHTML + value; } function testBrowser() { productVersion = ""; out("Suggested browser : "+window.navigator.userAgent+"<br/>"); if ( document.defaultCharset != '' && document.defaultCharset != undefined && document.characterSet == undefined && document.body) { productVersion=window.navigator.userAgent.substr(window.navigator.userAgent.indexOf("MSIE")+5,3); out("Detected browser : Internet Explorer <br/>Browser version in User-Agent is: "+ parseFloat(productVersion)); } if (window.opera && document.defaultCharset == undefined && document.characterSet != "" && document.characterSet != undefined && self.innerHeight) { productVersion=window.navigator.userAgent.substr(window.navigator.userAgent.indexOf("Opera")+6,4); out("Detected browser : Opera <br/>Browser version in User-Agent is: "+ parseFloat(productVersion)); } if (document.defaultCharset == undefined && !window.opera && document.characterSet != "" && (self.innerHeight)) { productVersion=window.navigator.userAgent.substr(window.navigator.userAgent.indexOf("Gecko")+6,8)+ ' ('+ window.navigator.userAgent.substr(8,3) + ')'; out("Detected browser : Mozilla <br/>Browser version in User-Agent is: "+ parseFloat(productVersion)); } if (productVersion == "") { out("Failed to fingerprint browser name , but i suggest it is "+window.navigator.userAgent); }} Пример страницы _http://underwater.xtoolz.ru/test.html
Способы решения проблем с кодировкой в Ajax [= Суть проблемы =] Ответ сервера при использовании Ajax по умолчанию приходит в кодировке "utf-8". Если запрашиваемая страница изначально имеет кодировку "windows-1251", то кириллические символы будут безвозвратно искажены свойством responseText. В таком случае вывод ответа сервера будет представлен знаками вопроса "?", или другими неопознанными символами. [= Способ решения =]Их много. Все способы можно разделить на две группы: изменение кодировки на стороне сервера и на стороне клиента. Когда мы имеем доступ к серверу, особых проблем обычно не возникает: хедеры, встроенные функции, перекодировка по таблицам символов. Описаний этого полно в нете. Обратная ситуация. Например, нашли мы уязвимость XSS, желаем использовать Ajax для незаметного получения каких-либо данных с других страниц на сервере. При этом: во-первых, кодировка у страниц "windows-1251", во-вторых, сервер в ответе на Ajax-запрос не указывает кодировку пересылаемых данных. В таких случаях возникает необходимость изменить кодировку уже на стороне клиента. Универсального способа для этого нет. Для каждого браузера (группы браузеров) они свои. Эти способы, являясь от части продуктом моего обобщения разрозненной информации, а отчасти моего собственного творчества, я представляю. [= Вариант, работающий во всех основных браузерах =] test.html (необходимо убирать пробелы-разрывы, которые вставляет сайт) PHP: <html> <div id=qwerty></div> <script> if (window.execScript) window.execScript('Function BinaryToString(Binary) \r cl1=1 \r cl2=1 \r cl3=1 \r L=LenB(Binary) \r Do While cl1<=L pl3=pl3&Chr(AscB(MidB(Binary,cl1,1))) \r cl1=cl1+1 \r cl3=cl3+1 \r If cl3>300 Then \r pl2=pl2&pl3 \r pl3="" \r cl3=1 \r cl2=cl2+1 \r If cl2>200 Then \r pl1=pl1&pl2 \r pl2="" \r cl2=1 \r End If \r End If \r Loop \r BinaryToString=pl1&pl2&pl3 \r End Function', 'VBScript'); var request=false; try {request=new XMLHttpRequest();} catch (forIE) {request=new ActiveXObject('Msxml2.XMLHTTP');} function ReadFile() { request.open("GET", 'text.html'); if (request.overrideMimeType) { request.overrideMimeType('text/html; charset=windows-1251'); request.onreadystatechange=override; } else request.onreadystatechange=readResponse; request.send(null); } function override() { if (request.readyState == 4) { request.open("GET", 'text.html'); request.onreadystatechange=readResponse; request.send(null); } } function readResponse() { if (request.readyState == 4) { if (request.overrideMimeType) document.getElementById('qwerty').innerHTML=request.responseText; else document.getElementById('qwerty').innerHTML=BinaryToString(request.responseBody); } } </script> <input type=button value='Жмах' onclick='ReadFile()'> </html> text.html Code: <html>Здесь что-нибудь на русском</html> А теперь по каждому браузеру в отдельности, чтобы стало понятно тем, кто не разобрался. 1) Internet Explorer Объекты Msxml2.XMLHTTP и XMLHttpRequest (IE 7.0) в этом браузере имеют фирменное свойство - "responseBody". В нем находится ответ сервера не в обычном строчном, а в бинарном виде. То есть в том виде, когда еще он не распарсился в соответствии с какой-либо кодировкой. В данном случае именно эта сторона для наc имеет значение. Будем парсить бинарный ответ самостоятельно. В стандартном JavaScript функций для работы с таким бинарным ответом сервера нет. IE имеет несколько элементов управления ActieX, которые могут это делать, но в некоторых случаях они из соображений безопасности бывают выключены. Имеется отличный способ обработки такого ответа с помощью VBScript, в котором присутствуют необходимые для этого встроенные функции. VBScript-функция Code: <script language=vbscript> Function BinaryToString(Binary) 'Antonin Foller, http://www.pstruh.cz 'Optimized version of a simple BinaryToString algorithm. Dim cl1, cl2, cl3, pl1, pl2, pl3, L cl1 = 1 cl2 = 1 cl3 = 1 L = LenB(Binary) Do While cl1<=L pl3 = pl3 & Chr(AscB(MidB(Binary,cl1,1))) 'Аналогов функций AscB() и MidB() в js нет. cl1 = cl1 + 1 cl3 = cl3 + 1 If cl3 > 300 Then pl2 = pl2 & pl3 pl3 = "" cl3 = 1 cl2 = cl2 + 1 If cl2 > 200 Then pl1 = pl1 & pl2 pl2 = "" cl2 = 1 End If End If Loop BinaryToString = pl1 & pl2 & pl3 End Function </script> Внедряем vbs-функцию в js с помощью фирменной функции IE - execScript() (убрать пробел в предпоследнем упоминании функции BinaryToString) PHP: <html> <div id=qwerty></div> <script> window.execScript('Function BinaryToString(Binary) \r cl1=1 \r cl2=1 \r cl3=1 \r L=LenB(Binary) \r Do While cl1<=L pl3=pl3&Chr(AscB(MidB(Binary,cl1,1))) \r cl1=cl1+1 \r cl3=cl3+1 \r If cl3>300 Then \r pl2=pl2&pl3 \r pl3="" \r cl3=1 \r cl2=cl2+1 \r If cl2>200 Then \r pl1=pl1&pl2 \r pl2="" \r cl2=1 \r End If \r End If \r Loop \r BinaryToString=pl1&pl2&pl3 \r End Function', 'VBScript'); var request = new ActiveXObject('Msxml2.XMLHTTP'); function ReadFile() { request.open('GET', 'text.html'); request.onreadystatechange=readResponse; request.send(null); } function readResponse() { if (request.readyState == 4) document.getElementById('qwerty').innerHTML=BinaryToString(request.responseBody); // передаем в функцию BinaryToString бинарный ответ сервера в качестве параметра и помещаем в див результат ее работы } </script> <input type=button value='Жмах' onclick='ReadFile()'> </html> 2) FireFox, Netscape Используется метод overrideMimeType() объекта реквест PHP: <html> <div id=qwerty></div> <script> var request = new XMLHttpRequest(); function ReadFile() { request.open("GET", 'text.html'); request.overrideMimeType('text/html; charset=windows-1251'); // метод переопределяет заголовок "Content-Type" от сервера request.onreadystatechange=readResponse; request.send(null); } function readResponse() { if (request.readyState == 4) document.getElementById('qwerty').innerHTML=request.responseText; } </script> <input type=button value='Жмах' onclick='ReadFile()'> </html> 3) Opera Метод overrideMimeType() предусмотрен в этом браузере в объекте реквест, однако в текущей версии 9.24 кодировку он не переопределяет. У данного браузера имеется другая особенность. Состоит она в автоматическом определении кодировки контента. То есть, когда запрашиваешь аяксом страницу в 'windows-1251' первый раз (с хоста), она выводится искаженной. Во второй раз та же страница отображается уже корректно. Данную особенность мы и будем использовать. PHP: <html> <div id=qwerty></div> <script> var request = new XMLHttpRequest(); function ReadFile() { request.open("GET", 'text.html'); // первый запрос request.onreadystatechange=override; request.send(null); } function override() { if (request.readyState == 4) { request.open("GET", 'text.html'); // второй запрос request.onreadystatechange=readResponse; request.send(null); } } function readResponse() { if (request.readyState == 4) // во второй раз, поскольку мы не разорвали соединение, состояние готовности сразу равно 4, в свойство попадает ответ сервера, находящийся в памяти. document.getElementById('qwerty').innerHTML=request.responseText; } </script> <input type=button value='Жмах' onclick='ReadFile()'> </html> В действительности не происходит ожидания ответа сервера при втором запросе, результат выводится сразу. Потеря времени ничтожна мала. Автоматическое определение кодировки Оперой производится независимо от установленной пользователем (пользовательской кодировкой может не быть "win-1251"), а также от настроек кэширования. Ключи поиска: кодировка Ajax кодировка перекодировка Ajax перекодировка UTF-8 Win-1251
Распознавание браузера на стороне клиента [= Вводные замечания =] 1. Скрипт предназначен для распознавания браузера юзера самим браузером юзера, минуя navigator.userAgent. Аналогов ему нет. 2. Нижепредставленный скрипт отличается от скрипта распознавания gemaglabin'a в первом сообщении тем, что: А) распознает не только группу браузеров, основанных на движке Gecko (Firefox, Netscape Navigator, Mozilla), но и сами эти браузеры внутри группы; Б) распознает конкретные версии браузеров или диапазоны версий, внутри которых наборы объектов, свойств и методов реализованной модели javascript характеризуются определенным постоянством. В) Мда, и код у него больше. 3. В качестве признаков идентификации были взяты две особенности: Первая: само наличие или отсутствие объектов, свойств и методов в модели javascript браузера, набор которых изменяется от версии к версии. Вторая: возможность вывода этих объектов, свойств и методов в цикле for ... in. Даже имеющиеся объекты-методы не всегда доступны к просмотру в цикле for ... in. Этот показатель также переменен от версии к версии. 4. Разумеется, в строгом смысле скрипт нельзя назвать скриптом на javascript. В нем использованы как средства Jscript, так и фирменные возможности других браузеров, не предусмотренные стандартами javascript. [= Скрипт =] PHP: var result=''; // сюда будем записывать результат идентификации if(window.opera) { result+='Opera '; // уже точно Opera var d=new Array(); for (e in document) d.push(e); d=d.toString(); if (window.XSLTProcessor) // 9.0-9.25 { if (d.indexOf('execCommand')==-1) result+='9.24'; else { if (document.selectNodes) { if (d.indexOf('postMessage')==-1) result+='9.25'; else result+='9.02-9.23'; } else { if (d.indexOf('onload')!=-1) result+='9.01'; else result+='9.0'; } } } else if (document.all) // 8.0-8.54 { if (!opera.SRPNumber) result+='8.50-8.54'; else { if (document.postMessage) result+='8.01-8.02'; else result+='Opera 8.0'; } } else // 7.02-7.54 { if (window.navigate) result+='7.50-7.54'; else { if (window.getComputedStyle) result+='7.20-7.23'; else { if (window.VXMLAudioRecording) result+='7.11'; else result+='7.02-7.1'; } } } } else if (document.layers) result+='Netscape Navigator 4.x'; // Old Netscape else if (document.defaultCharset == undefined && !window.opera) // Gecko based { var a=new Array(); for (b in document.body) a.push(b); a=a.toString(); var h=new Array(); for (i in document) h.push(i); h=h.toString(); if (document.defaultView.globalStorage) { if (document.defaultView.getInterface) result+='Firefox 2.0-2.0.0.11'; else result+='Netscape Navigator 9.0-9.0.0.5'; } else { if (document.defaultView.getInterface && window.Components) result+='Firefox 1.5-1.5.0.8'; else { if (a.indexOf('addEventListener')==-1) { if (h.indexOf('preferredStylesheetSet')!=-1) result+='Firefox 1.0.6-1.0.7'; else result+='Mozilla 1.7.10-1.7.13'; } else { if (document.defaultView.setTransparency) result+='Netscape Navigator 8.1'; else { if (window.pkcs11.addmodule && window.OPEN_NEW_WIN_ONLY) result+='Netscape Navigator 8.0.2-8.0.4'; else { if (document.actualEncoding) { if (h.indexOf('preferredStylesheetSet')!=-1) result+='Firefox 1.0-1.0.4'; else result+='Firefox 0.8-0.9 or Mozilla 1.7-1.7.8 or Netscape Navigator 7.2'; } else if (sidebar.CHECK_ANONYMOUS) result+='Netscape Navigator 7.0-7.02'; } } } } } } else // IE { var JScript=''; /*@cc_on @*/ /*@ JScript=@_jscript_version @*/ JScript==3.0? result+='Internet Explorer 4.0': JScript==5.0? result+='Internet Explorer 5.0': JScript==5.5? result+='Internet Explorer 5.5': JScript==5.6? result+='Internet Explorer 6.0': JScript==5.7? result+='Internet Explorer 7.0': result+='Browser unknown'; } document.write('<b><font size=4>Result of fingerprinting:</font></b> '+result+'<br /><b><font size=4>Browserinfo (navigator.userAgent):</font></b> '+window.navigator.userAgent); //\\ LeverOne //\\ [= Заключительные замечания =] 1. О недостатках А) Распознавание основано на предположении, что клиент использует один из тех браузеров, на которые нацелено распознавание: FireFox, Mozilla, Netscape Navigator, Opera, Internet Explorer. Остальные могут быть распознаны некорректно, хотя многое сделано, чтобы такие браузеры были обозначены отдельно как "неопознанные". Б) Брались во внимание только финальные версии, но не альфа, бета и т.д. В) Просмотр исходного кода страницы до распознавания может повлечь ошибку идентификации. Необходимо просматривать его после получения результата. Г) Из-за того, что объекты-методы могут то появляться, то исчезать в новых версиях (ибо процесс расширения возможностей нелинеен во времени) скрипт может давать ошибочные результаты при распознавании более новых версий, чем заложено в нем самом. Например, Opera 9.25 ближе к 9.23, чем к 9.24. Д) Тестировалось всё под Виндовс, как те же самые браузеры поведут в других OC, утверждать не могу. 2. Версии распознающихся браузеров: IE: 4.0, 5.0, 5.5, 6.0, 7.0 Opera: 7.02, 7.03, 7.10, 7.11, 7.20, 7.21, 7.22, 7.23, 7.50, 7.51, 7.52, 7.53, 7.54, 8.0, 8.01, 8.02, 8.50, 8.51, 8.52, 8.53, 8.54, 9.0, 9.01, 9.02, 9.10, 9.20-9.25 _http://arc.opera.com/pub/opera/win Firefox: 0.8, 0.9, 1.0, 1.0.1-1.0.7, 1.5, 1.5.0.1-1.5.0.8, 2.0, 2.0.0.1-2.0.0.11 Netscape Navigator: 4.x, 7.0, 7.01, 7.02, 7.2, 8.02, 8.03, 8.04, 8.1, 9.0, 9.0.0.1-9.0.0.5 _http://browser.netscape.com/downloads/archive Mozilla: 1.7, 1.7.1-1.7.13 _http://www.mozilla.org/releases/
Кодировка утф предназначена для англоязычных стран восновном. Не понимаю зачем нужно посылать инфу в одной кодировке а получать в другой? PHP: $objAjax = new xajax(); // компонент класса xajax $objAjax->setCharEncoding("windows-1251"); // выставляем кодировку Что делать если отключен js и другие компоненты у пользователя все проверки пойдут лесом? И еще как можно точно определить поисковых ботов на js.