dbroot.v5文件详解

dbRoot.v5是GE的主要的配置文件,其中包括层列表,提供程序列表(图层和快照的内容提供程序),图层的显示样式,可能的服务器列表(天空,火星等),当前数据库版本和当前密钥,用于解密所有传输的数据。

目前,这个文件可以以两种格式传输(有条件:第一版和第二版),二进制结构不同,但最后携带相同的数据:

  • 适用于5.1及以下客户(较小版本的客户) - 第一版
  • 对于5.2及更早版本的客户(旧版客户端) - 第二版

此外,客户端5.2.1.1329(来自标尺5.2的第一个客户端)以及稍后支持该文件的两个版本(第二个版本是默认版本,第一个版本仅在第二个版本文件不可用时加载)。

首先从服务器请求此文件。如果无法从Internet下载此文件,则客户端会尝试从缓存中下载该文件(第一版文件存储在dbCache.dat中,第二版存储在dbroot_cache中)。在这种情况下,如果客户端无法从缓存中下载它(例如,缓存为空),则客户端的工作将被中断,并且将报告无法连接到服务器。

每次客户端启动时都会下载此文件(对于Sky,Mars和History服务器 - 每次会话一次,切换到此模式时)。

请求格式

客户端生成此文件请求的方式取决于Windows语言设置,GoogleEarth自己的设置,以及客户端的旧版本以及客户端的版本和类型。地球视图模式的典型查询示例:

 请求第一版文件:
   http://kh.google.com/dbRoot.v5?hl=ru-RU&gl=ru
 
 第二版的文件请求:
   http://kh.google.com/dbRoot.v5?hl=ru-RU&gl=ru&output=proto&cv=5.2.1.1329&ct=free
 
 其中,hl = ru-RU是用户的语言
      gl = ru  - 用户的位置
      output = proto  - 容器格式
      cv = 5.2.1.1329  - 客户端版本
      ct =免费 - 客户类型(免费/专业版)

关键

解密数据的密钥从第9个字节开始,长度为1016个字节。为了在解密算法中使用,必须补充8个零(在前面)到1024个字

原文地址:https://greverse.bitbucket.io/dbroot.htm

相关代码:python 代码地址

 

import os, sys, requests, struct, zlib

# urls:
# kh.google.com/dbRoot.v5 < 秘钥和地图版本信息
# kh.google.com/flatfile?q2-0-q.705 < QTree数据
# kh.google.com/flatfile?f1-030-i.704 < 瓦片图像
# /dbRoot.v5?hl=zh-hans-cn&gl=cn&output=proto&cv=5.2.1.1588&ct=free
# 1. 

def Eval(fname, key):
    # 解码数据
    if (os.path.exists(fname)==False): return None
    if (os.path.getsize(fname)==0): return None
    f = open(fname, 'rb+')
    data = f.read()                             # 读取文件内容
    f.close()
    #outdata = [0 for i in range(len(data))]    # 创建一个结果数组
    outdata = bytearray(len(data))              # 创建一个结果数组
    
    index = 16
    for i in range(0, len(data)):
        outdata[i] = ord(data[i]) ^ ord(key[index+8])
        index += 1
        if (index % 8 == 0): index += 16
        if (index >= 1016): index = (index + 8) % 24
    return outdata

def EvalData(data, key):
    # 解码数据
    outdata = bytearray(len(data))              # 创建一个结果数组
    index = 16
    for i in range(0, len(data)):
        outdata[i] = ord(data[i]) ^ ord(key[index+8])
        index += 1
        if (index % 8 == 0): index += 16
        if (index >= 1016): index = (index + 8) % 24
    return outdata

def ReadKEY(fname):
    # 读取KEY文件
    f = open(fname, 'rb+')
    data = f.read()
    f.close()
    return data

def ReadVersion(fname):
    # 读取dbRoot.v5文件里的版本号
    if (os.path.exists(fname)==False): return None
    if (os.path.getsize(fname)==0): return None
    f = open(fname, 'rb+')
    f.seek(6)
    value = f.read(2)
    f.close()
    version = struct.unpack('h', value)[0]
    version = version ^ 0x4200
    return version

def ReadDBRoot():
    # 读取dbRoot.v5文件
    # 详细说明 http://greverse.bitbucket.org/dbroot.htm
    # 00-03: 固定 9464874E
    # 04-05: 数据版本 6600
    # 06-07: 地图版本 比如 C240 需要与 0x4200 进行异或运算得出最终版本
    # 08-1023: 数据秘钥共1016字节
    # 1024-: 加密的XML数据
    pass

def Tile2QuadKEY(tileX, tileY, zoom):
    # 瓦片坐标转四叉树
    result = '0'
    for i in range(zoom, 0, -1):
        digit = 0
        mask = 1 << (i - 1)
        if ((tileX & mask) != 0): digit += 1
        if ((tileY & mask) != 0): digit += 2
        # 由于谷歌四叉树算法和必应四叉树算法不一致
        # 所以取巧采用对照表的方法可以解决 但第一位始终是0
        # 对照表
        # 必应 -> 谷歌
        # 0 -> 3
        # 1 -> 2
        # 2 -> 0
        # 3 -> 1
        if (digit == 0): result += '3'
        elif (digit == 1): result += '2'
        elif (digit == 2): result += '0'
        elif (digit == 3): result += '1'
    return result

def QuadKEY2Tile(nums):
    # 四叉树转 反转的时候也必须通过对照表
    tileX = 0
    tileY = 0
    nums = nums[1:]       # 第一位是0所以取掉
    zoom = len(nums)
    
    for i in range(zoom, 0, -1):
        mask = 1 << (i - 1)
        if (nums[zoom - i] == '3'):
            continue
        elif (nums[zoom - i] == '2'):
            tileX |= mask
            continue
        elif (nums[zoom - i] == '0'):
            tileY |= mask
            continue
        elif (nums[zoom - i] == '1'):
            tileX |= mask
            tileY |= mask
            continue
    return tileX, tileY, zoom

def Hex2Time(data):
    # 十六进制转时间
    # data: 传入16进制数据
    month = int(data & 0xF)         # 月
    day = int((data & 0x1F0)>>4)    # 日
    year = int((data & 0xFFE00)>>9) # 年
    return year, month, day

def Time2Hex(year, month, day):
    # 时间转十六进制
    pass


if __name__ == '__main__':
    print '[==DoDo==]'
    print 'GE Tiles.'
    print 'Encode: %s' %  sys.getdefaultencoding()

    # 解密瓦片数据
    #keydata = ReadKEY('data/key.bin')
    #imgdata = Eval('data/_flatfile-f1c-0201202-t.705', keydata)
    #f = open('out.jpg', 'wb')
    #f.write(imgdata)
    #f.flush()
    #f.close()

    # 时间字符串转时间
    #Hex2Time(int('0xfa99b', 16))

    # 瓦片坐标和四叉树互转
    #print Tile2QuadKEY(3, 5, 3)
    #print 'X:%s Y:%s Z:%s' % QuadKEY2Tile('0201202')

    # 读取地图版本
    #print ReadVersion('data/dbRoot.v5')

    # 解码QTree数据
    keydata = ReadKEY('data/key.bin')
    zlibdata = Eval('data/_flatfile-q2-0-q.706', keydata)

    f = open('data.z', 'wb')    # 解密后的压缩数据
    f.write(zlibdata)
    f.flush()
    f.close()

    unzlibdata = zlib.decompress(str(zlibdata[8:]))
    f = open('data.u', 'wb')    # 解压后的真实数据
    f.write(unzlibdata)
    f.flush()
    f.close()

    '''
    # 下载L2级别影像进行测试
    keydata = ReadKEY('data/key.bin')
    
    for x in range(0, 4):
        for y in range(0, 4):
            nums = Tile2QuadKEY(x, y, 2)
            url = 'http://kh.google.com/flatfile?f1-{0}-i.705'.format(nums)
            response = requests.get(url, stream=True)
            data = response.raw.read()
            savefile = 'out/_{0}.dat'.format(nums)
            f = open(savefile, 'wb')
            f.write(data)
            f.flush()
            f.close()
            savefile = 'out/{0}.jpg'.format(nums)
            data = EvalData(data, keydata)
            f = open(savefile, 'wb')
            f.write(data)
            f.flush()
            f.close()
    '''

    print 'OK.'

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值