--[[ <HCExtension>@name Google Earth caching@author nadenj@mail.ru@version 0.05sr1@description Google Earth flatfiles caching@rule kh(mdb)?\.google\.com/flatfile\?@event RequestHeaderReceived/request</HCExtension> ]]--[[********************************************************************************* Учитывать: 1. Не рассчитано на использование дополнительного кэша (я не нашел способа определять с помощью Lua-API, в каком из кэшей найден файл) 2. Будет неправильно работать при отключении чтения из кэша (это при желании можно доработать)*************************************************************************************]]-- Переводит целое число в 4-символьную строку, содержащую его машинное представление--(для записи целого в память или файл) local function IntToChars(int) local ch = '' for j=1,4 do ch = ch .. string.char(int%256) int = math.floor(int/256) end return ch end -- обратная функция local function CharsToInt(chr) local int = 0 for j=1,4 do int = int + string.byte(chr:sub(j,j))*256^(j-1) end return int end-- local URLBaselocal function OriginURL(cut_url) if cut_url:find('+', 1, true) then return re.replace(URLBase, '===', cut_url) end return re.replace(URLBase, '===.*', cut_url)end-- ********** О Б Р А Б О Т К А З А Г О Л О В К А З А П Р О С А ********** function request() -- if hc.url:find('geauth') then -- hc.put_msg('ops')-- local f=io.open(hc.get_cache_file_name(hc.url), 'rb')-- hc.answer_body = f:read('*a')-- f:close() -- hc.answer_header = 'HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nExpires: 0\r\n' ..-- 'Cache-Control: no-cache,no-store\r\nSet-Cookie: PREF=ID=04c59454d2abb6b7:TM=1243710370:LM=1243710370:S=YdBzseUhw6Z4z3xu; ' ..-- 'expires=Mon, 30-May-2011 19:06:10 GMT; path=/; domain=.google.com\r\nDate: Sat, 30 May 2009 19:06:10 GMT\r\nServer: btfe\r\n' ..-- 'Content-Length: ' .. #hc.answer_body .. '\r\nConnection: Close\r\n\r\n' -- return -- end local URLTail = re.replace(hc.url, [[(^http://kh(mdb)?\.google\.com/flatfile\?(db=\w+&)?+)([^&]+)(.*)]], [[\4]]) URLBase = re.replace(hc.url, nil, [[\1===\5]]) -- если запрошенный файл не составной, то не обновляем его -- hc.put_to_log('+++++++++++++ ', URLTail, ' +++++++++++') if not URLTail:find('+', 1, true) then hc.action = 'dont_update' hc.monitor_string = 'GE: загружен' return end -- все остальное только для составных запрошенных файлов. В кэше их не сохраняем, -- разбиваем на простые, каждый из которых сохраняем в кэш hc.action = 'dont_save' GE = {} i = 0 -- число подфайлов в запрашиваемом файле GE.not_in_cache_count = 0 -- число подфайлов, отсутствующих в кэше -- для каждого подфайла сохраним его url и признак наличия в кэше local not_cached_url = '' for file in URLTail:gmatch('[^+]+') do i = i+1 GE[i] = {url=file} GE[i].fname, GE[i].in_cache = hc.get_cache_file_name(OriginURL(file)) if GE[i].in_cache then local cf = io.open(GE[i].fname, 'rb') if cf then GE[i].body = cf:read('*a') cf:close() hc.put_to_log('GE: Прочли из кэша файл ', GE[i].fname) else hc.put_to_log('GE: Не удалось прочесть из кэша файл ', GE[i].fname) hc.put_msg('GE: Не удалось прочесть из кэша файл ', GE[i].fname) end else GE.not_in_cache_count = GE.not_in_cache_count + 1 not_cached_url = not_cached_url .. '+' .. file end end -- если все куски запрашиваемого файла есть в кэше, то собираем его и отдаем if GE.not_in_cache_count==0 then local header = '\1' .. string.char(i) -- создаем начало заголовка собираемого файла local body = '' -- здесь накапливаем тело собираемого файла local j = 1 repeat local cf = io.open(GE[j].fname, 'rb') if cf then header = header .. IntToChars(2+4*i+#body) -- дописываем смещение j-го подфайла в заголовок body = body .. cf:read('*a') -- дописываем тело j-го подфайла к собираемому файлу cf:close() j = j + 1 end until j>i hc.answer_body = header .. body hc.answer_header = 'HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\nServer: btfe\r\nContent-Length: ' .. #hc.answer_body .. '\r\nConnection: Close\r\n\r\n' hc.monitor_string = 'GE: составной, всё из кэша' else GE.body = '' GE.files_count = i -- формируем новый URL, куда войдут только отсутствующие в кэше части not_cached_url = not_cached_url:gsub('+', '', 1) -- и исправляем соответственно заголовок запроса к серверу if not_cached_url:find('+', 1, true) then hc.request_header = re.replace(hc.request_header, [[.*?\?(db=\w+&)?+\K[^&\s]+]], not_cached_url) else hc.request_header = re.replace(hc.request_header, [[.*?\?(db=\w+&)?+\K\S+]], not_cached_url) end hc.call_me_for('BeforeAnswerBodySend', 'body') endend-- ********** О Б Р А Б О Т К А Т Е Л А О Т В Е Т А **********function body() GE.body = GE.body .. hc.answer_body -- тело полученного из интернет ответа local body = '' -- здесь накапливаем итоговое тело ответа if not hc.last_part then hc.answer_body = '' return end local i = GE.files_count local k = 0 local header = '\1' .. string.char(i) -- создаем начало заголовка собираемого файла for j=1,i do header = header .. IntToChars(2+4*i+#body) -- дописываем смещение j-го подфайла в заголовок if GE[j].in_cache then body = body .. GE[j].body else local bb if GE.not_in_cache_count==1 then bb = GE.body else k = k + 1 bb = GE.body:sub(CharsToInt(GE.body:sub(k*4-1,k*4+2))+1, k<GE.not_in_cache_count and CharsToInt(GE.body:sub(3+k*4,3+(k+1)*4-1)) or -1) end hc.prepare_path(GE[j].fname) local ff = io.open(GE[j].fname, 'wb') if ff then ff:write(bb) -- пишем j-й подфайл в кэш ff:close() hc.put_to_log('GE: Записали в кэш файл ', GE[j].fname) -- удалим из RAM-кэша и текущего потока возможную информацию о том, что j-го подфайла в кэше нет hc.update_url_info(OriginURL(GE[j].url)) end body = body .. bb end end hc.answer_body = header .. body hc.monitor_string = (GE.not_in_cache_count<i) and 'GE: составной, из сети и кэша' or 'GE: составной, загружен полностью'end
17.06.09 12:26:47,354 # 2031 <<< URL: http://kh.google.com/geauthHTTP/1.1 200 OKContent-Type: application/octet-streamExpires: 0Cache-Control: no-cache,no-storeSet-Cookie: PREF=ID=f55b6a75f4d129bc:TM=1245216523:LM=1245216523:S=RDN8rR2r9oCmV4uw; expires=Fri, 17-Jun-2011 05:28:43 GMT; path=/; domain=.google.comDate: Wed, 17 Jun 2009 05:28:43 GMTServer: btfeContent-Length: 112Connection: keep-alive17.06.09 12:26:47,448 # 2032/4718 >>> URL: http://mw2.google.com/mw-earth-vectordb/gallery_layers/icons/places.pngnoReqDo:GET http://mw2.google.com/mw-earth-vectordb/gallery_layers/icons/places.png HTTP/1.1Accept: text/plain, text/html, text/xml, text/xml-external-parsed-entity, application/octet-stream, application/vnd.google-earth.kml+xml, application/vnd.google-earth.kmz, image/*If-Modified-Since: Mon, 15 Jun 2009 07:47:18 GMTUser-Agent: GoogleEarth/4.2.0205.5730(Windows;Microsoft Windows XP (Service Pack 1);ru-RU;kml:2.2;client:Free;type:default)Host: mw2.google.comConnection: Keep-Alive17.06.09 12:26:47,558 # 2032/4718 <<< URL: http://mw2.google.com/mw-earth-vectordb/gallery_layers/icons/places.pngHTTP/1.1 304 Not Modified (HC)Server: HandyCache/1.00 RC2 (1.0.0.180) UNSTABLEContent-Length: 0Connection: Keep-alive17.06.09 12:26:51,026 # 2031: DNS resolve GET http --> Err 12317.06.09 12:26:51,136 # 2031 <<< URL: GET http://kh.google.com/flatfile?GET http://kh.google.com/flatfile?q2-03103132-q.203+q2-03103123-q.203+f1c-03100332-d.5378.200&v=1&v=1Connection to GET http:8017.06.09 12:26:51,276 # 2032: DNS resolve kh.google.com --> 72.14.203.190 (From cache)17.06.09 12:26:51,401 # 2032 <<< URL: http://kh.google.com/flatfile?q2-03103003-q.203Connection to 72.14.203.190:8017.06.09 12:26:51,604 # 2032: Outbound Connection, Local port: 466017.06.09 12:26:51,698 # 2032/4720 >>> URL: http://kh.google.com/flatfile?q2-03103003-q.203GET /flatfile?q2-03103003-q.203 HTTP/1.1Accept: text/plain, text/html, text/xml, text/xml-external-parsed-entity, application/octet-stream, application/vnd.google-earth.kml+xml, application/vnd.google-earth.kmz, image/*Cache-Control: no-cache, no-storeCookie: $Version="0"; SessionId=XxJsOgADEAEADwAwbMslVKwmKBmGHjrI8htaFm/fQHQ/Ix9jIouSdX/ubvoRh4OWub/txDJH2shfI3N2; State=1User-Agent: GoogleEarth/4.2.0205.5730(Windows;Microsoft Windows XP (Service Pack 1);ru-RU;kml:2.2;client:Free;type:default)Host: kh.google.comConnection: Keep-AlivePragma: no-cache17.06.09 12:26:51,808 # 2032 <<< URL: http://kh.google.com/flatfile?q2-03103003-q.203HTTP/1.1 200 OKDate: Wed, 17 Jun 2009 05:28:48 GMTPragma: no-cacheExpires: Fri, 01 Jan 1990 00:00:00 GMTCache-Control: no-cache, must-revalidateContent-Type: application/octet-streamServer: btfeContent-Length: 456Connection: keep-alive
-- формируем новый URL, куда войдут только отсутствующие в кэше части not_cached_url = OriginURL(not_cached_url:gsub('+', '', 1)):gsub('.-%?', '', 1) -- и исправляем соответственно заголовок запроса к серверу hc.request_header = re.replace(hc.request_header, [[.*?\?\K\S+]], not_cached_url, false)