Я давно думал о том, чтобы написать систему управления своей коллекцией софта, но только недавно нашлось время. И первым шагом было автоматизировать проверку новых версий программ. Большинство программ не имеют встроенного механизма проверки наличия новых версий и тем более, автоматического обновления, поэтому приходилось информацию о них получать методом парсинга страниц офф. сайтов. В тоже время глупо было бы не воспользоваться имеющимися системами, учитывая что они дают куда более точную информацию о новых версиях. Итак, начнем с самого крепкого орешка - Оперы. На то, чтобы понять как работает её система обновлений у меня ушло 3 дня, поэтому я просто не поделиться полученной информацией =)
На данный момент Opera использует два протокола проверки наличия новых версий:
1. Используется для обновления текущих стабильных версий 9.xx.
Шифрование не используется, все передается по протоколу HTTP. Сервер обновлений - xml.opera.com.
Проверить его работу можно очень просто: достаточно перейти по ссылке
http://xml.opera.com/update/. Если сделать это в опере - вам предстанет XML документ с перечислением последних версий для различных локализаций.
GET /update/?timesincelastcheck=585 HTTP/1.1
User-Agent: Opera/9.64 (Windows NT 5.2; U; MRA 5.4 (build 02647); ru) Presto/2.1.1
Host: xml.opera.com
Connection: Keep-Alive, TE
TE: deflate, gzip, chunked, identity, trailers
HTTP/1.1 200 OK
Date: Tue, 09 Jun 2009 08:10:59 GMT
Server: Apache/2.2.3 (Debian) mod_apreq2-20051231/2.6.0 mod_perl/2.0.2 Perl/v5.8.8
Connection: close
Transfer-Encoding: chunked
Content-Type: text/xml
99f
<?xml version="1.0" encoding="utf-8"?>
<versioncheck spoof="1241625280" bspit="1242739781">
<idn>:jp:de:se:kr:tw:cn:at:dk:ch:li:museum:hu:xn--kgbechtv:xn--hgbk6aj7f53bba:xn--0zwm56d:xn--g6w251d:xn--80akhbyknj4f:xn--11b5bs3a9aj6g:xn--jxalpdlp:xn--9t4b11yi5a:xn--deba0ad:xn--zckzah:xn--hlcj6aya9esc7a:</idn>
<latestversion lang="af">9.27</latestversion>
<latestversion lang="be">9.64</latestversion>
<latestversion lang="bg">9.64</latestversion>
<latestversion lang="ca">9.27</latestversion>
<latestversion lang="cs">9.64</latestversion>
<latestversion lang="da">9.64</latestversion>
<latestversion lang="de">9.64</latestversion>
<latestversion lang="el">9.64</latestversion>
<latestversion lang="en">9.64</latestversion>
<latestversion lang="en-gb">9.64</latestversion>
<latestversion lang="en-us">9.27</latestversion>
<latestversion lang="es-es">9.64</latestversion>
<latestversion lang="es-la">9.64</latestversion>
<latestversion lang="et">9.64</latestversion>
<latestversion lang="fi">9.64</latestversion>
<latestversion lang="fr">9.64</latestversion>
<latestversion lang="fr-ca">9.64</latestversion>
<latestversion lang="fy">9.64</latestversion>
<latestversion lang="hi">9.64</latestversion>
<latestversion lang="hr">9.64</latestversion>
<latestversion lang="hu">9.64</latestversion>
<latestversion lang="id">9.64</latestversion>
<latestversion lang="it">9.64</latestversion>
<latestversion lang="ja">9.64</latestversion>
<latestversion lang="ka">9.64</latestversion>
<latestversion lang="ko">9.64</latestversion>
<latestversion lang="lt">9.64</latestversion>
<latestversion lang="mk">9.64</latestversion>
<latestversion lang="nb">9.64</latestversion>
<latestversion lang="nl">9.64</latestversion>
<latestversion lang="nn">9.64</latestversion>
<latestversion lang="pa">9.27</latestversion>
<latestversion lang="pl">9.64</latestversion>
<latestversion lang="pt">9.64</latestversion>
<latestversion lang="pt-br">9.64</latestversion>
<latestversion lang="ru">9.64</latestversion>
<latestversion lang="sv">9.64</latestversion>
<latestversion lang="ta">9.64</latestversion>
<latestversion lang="te">9.64</latestversion>
<latestversion lang="th">9.27</latestversion>
<latestversion lang="tr">9.64</latestversion>
<latestversion lang="uk">9.64</latestversion>
<latestversion lang="zh-cn">9.64</latestversion>
<latestversion lang="zh-tw">9.64</latestversion>
</versioncheck>
0
Судя по всему, алгоритм работы проверки в данном случае таков: получаем XML документ, парсим, выбираем ноду с нужной нам локализацией и сравниваем версии. Если версия из документа больше текущей версии программы, говорим о доступности обновления.
Плюсы такого подхода - можно проверять обновления сразу для различных локализаций.
2. Используется начиная с версии 10.00 (9.80):
По умолчанию, все данные передаются по протоколу HTTPS. Судя по дампу пакетов, соединение происходит все же с сервером xml.opera.org, хотя в поле Host, равно как и в opera:config фигурирует autoupdate.opera.com.
Кстати именно через него можно на данный момент поменять сервер обновлений или просто сменить протокол проверки обновлений с https на http: opera:config#AutoUpdate.
У меня есть два предположения относительно различия протоколов: либо этот протокол используется только для Alpha/Beta версий (что вряд ли), либо это новый протокол который будет использоваться для проверки новых версий начиная с версии 10.xx (9.80).
POST / HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 5.2; U; en) Presto/2.2.15 Version/10.00
Host: autoupdate.opera.com
Content-Type: application/x-www-form-urlencoded
<?xml version="1.0" encoding="utf-8"?><oau:versioncheck schema-version="1.0" update-level="3" xmlns:oau="urn:OperaAutoupdate"><opera><version>10.00</version><build-number>1535</build-number><language>en</language><edition/><time-since-last-check>322</time-since-last-check><should-serve-all>1</should-serve-all><modules><browserjs-timestamp>1242739880</browserjs-timestamp><spoof-timestamp>1241625280</spoof-timestamp><dictionary-timestamp>1242743614</dictionary-timestamp><dictionary><language version="1.0">ru</language><language version="1.0">en</language></dictionary></modules></opera><operating-system><platform>Windows</platform><version>XP</version><architecture>i386</architecture></operating-system><package><package-type>msi</package-type><gcc/><qt/></package></oau:versioncheck>
HTTP/1.1 200 OK
Date: Tue, 09 Jun 2009 09:30:24 GMT
Server: Apache/2.2.3 (Debian) mod_apreq2-20051231/2.6.0 mod_perl/2.0.2 Perl/v5.8.8
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
Pragma: no-cache
Expires: Thu, 1 Jan 1970 00:00:01 GMT
Connection: close
Transfer-Encoding: chunked
Content-Type: text/xml; charset=utf-8
398
<?xml version="1.0" encoding="UTF-8"?>
<oau:versioncheck xmlns:oau="urn:OperaAutoupdate" version="1.0"><resources><downloadurl>http://www.opera.com/download</downloadurl></resources><file><name>Opera_1000_1551_en.msi</name><url>http://www.opera.com/download/get.pl?id=32080&location=148¬hanks=yes&sub=marine</url><urlalt>http://www.opera.com/download/get.pl?id=32080&location=148¬hanks=yes&sub=marine</urlalt><version>10.00</version><bnum>1551</bnum><size>7130316</size><lang delimiter=",">en</lang><type>Full</type><checksum>31d5eefc5c13580ee5f4e01faa31c33cb227eca229213dd58c4cba14d492cfb7</checksum><infourl>http://help.opera.com/updateinfo/?bnum=1551&opsys=Windows&version=10.00&edition=</infourl></file><setting><file>Opera6.ini</file><section>Network</section><key>IDNA White List</key><data>:jp:de:se:kr:tw:cn:at:dk:ch:li:museum:hu:</data></setting></oau:versioncheck>
0
Теперь разберем запрос и ответ. Запрос всегда строится по одному принципу:
<?xml version="1.0" encoding="utf-8"?>
<oau:versioncheck schema-version="1.0" update-level="3" xmlns:oau="urn:OperaAutoupdate">
<opera>
<version>10.00</version>
<build-number>1535</build-number>
<language>en</language>
<edition/>
<time-since-last-check>322</time-since-last-check>
<should-serve-all>1</should-serve-all>
<modules>
<browserjs-timestamp>1242739880</browserjs-timestamp>
<spoof-timestamp>1241625280</spoof-timestamp>
<dictionary-timestamp>1242743614</dictionary-timestamp>
<dictionary>
<language version="1.0">ru</language>
<language version="1.0">en</language>
</dictionary>
</modules>
</opera>
<operating-system>
<platform>Windows</platform>
<version>XP</version>
<architecture>i386</architecture>
</operating-system>
<package>
<package-type>msi</package-type>
<gcc/>
<qt/>
</package>
</oau:versioncheck>
Ответ же может отличаться в зависимости от того, доступна ли новая версия или нет:
<?xml version="1.0" encoding="UTF-8"?>
<oau:versioncheck xmlns:oau="urn:OperaAutoupdate" version="1.0">
<resources>
<downloadurl>http://www.opera.com/download</downloadurl>
</resources>
<file>
<name>Opera_1000_1551_en.msi</name>
<url>http://www.opera.com/download/get.pl?id=32080&location=148¬hanks=yes&sub=marine</url>
<urlalt>http://www.opera.com/download/get.pl?id=32080&location=148¬hanks=yes&sub=marine</urlalt>
<version>10.00</version>
<bnum>1551</bnum>
<size>7130316</size>
<lang delimiter=",">en</lang>
<type>Full</type>
<checksum>31d5eefc5c13580ee5f4e01faa31c33cb227eca229213dd58c4cba14d492cfb7</checksum>
<infourl>http://help.opera.com/updateinfo/?bnum=1551&opsys=Windows&version=10.00&edition=</infourl>
</file>
<setting>
<file>Opera6.ini</file>
<section>Network</section>
<key>IDNA White List</key>
<data>:jp:de:se:kr:tw:cn:at:dk:ch:li:museum:hu:</data>
</setting>
</oau:versioncheck>
или
<?xml version="1.0" encoding="UTF-8"?>
<oau:versioncheck xmlns:oau="urn:OperaAutoupdate" version="1.0">
<resources>
<downloadurl>http://www.opera.com/download</downloadurl>
</resources>
<setting>
<file>Opera6.ini</file>
<section>Network</section>
<key>IDNA White List</key>
<data>:jp:de:se:kr:tw:cn:at:dk:ch:li:museum:hu:</data>
</setting>
</oau:versioncheck>
Тут, судя по всему, проверка происходит уже на стороне сервера: ему передаются данные о текущей версии браузера, операционной системе, локализации и пр. и их на основе сервер определяет имеется ли в наличии подходящее обновление. Если да, то в ответе будет фигурировать нода <file> Эта система все больше напоминает
AUS (Application Update Service) используемую в продуктах Mozilla о которой я расскажу несколько позднее.