def getEvent(_logFile,_offset): _esignature = data_read(_logFile,_offset,'DWORDl') #0x45DECADE _offset+=4 _ofsPrev = data_read(_logFile,_offset,'DWORDl') #оффсет до предыдущего и следующего сообщения в #цепочке. Цепочка отсортированная хронологически _offset+=4 _ofsNext = data_read(_logFile,_offset,'DWORDl') _offset+=4 _ofsModuleName = data_read(_logFile,_offset,'DWORDl') #оффсет до структуры DBModuleName имени владельца события _offset+=4 _timestamp = UnixTimeToDataTime(data_read(_logFile,_offset,'DWORDl')) #секунд с 00:00:00 01/01/1970 _offset+=4 _flags = data_read(_logFile,_offset,'DWORDl') _i=4 _flag = [0,0,0,0,0] #Флаги for f in bin(_flags).split('b')[1][::-1]: #1: первое сообщение в цепочке; _flag[_i]=int(f) # только для внутреннего использования: *do not* use this flag _i-=1 #2: событие отправленно пользователем # если не установлен - событие получено пользователем #4: событие прочитано пользователем. It does not need # to be processed any more except for history. #8: событие содержит текст, написанный справа налево #16:событие содержит текст в utf-8 _offset+=4 _eventType = data_read(_logFile,_offset,'Wordl') #module-defined event type _offset+=2 _direction = 'out' if _flag[3] else 'in' _cbBlob = data_read(_logFile,_offset,'DWORDl') if _flag[0] else data_read(_logFile,_offset,'DWORDl')/3 #number of bytes in the blob _offset+=4 _text = '' for b in range(_cbBlob): _text += chr(data_read(_logFile,_offset,'Byte')[0])#the blob. module-defined formatting _offset+=1 #print 'event: ', hex(esignature),hex(ofsPrev),hex(ofsNext),hex(ofsModuleName),timestamp,flag,hex(eventType),cbBlob,text, return _esignature,_ofsPrev,_ofsNext,_ofsModuleName,_timestamp,_flag,_eventType,_direction,_text
def parseMraHistory(mra_file,messages): try: with open(mra_file,"rb") as logFile: offset_to_OT = data_read(logFile,0x10,'DWORDl') # OT - offset table end_id_mail = data_read(logFile,0x2C+data_read(logFile,offset_to_OT+4,'DWORDl'),'DWORDl') # Номер последнего емэйла в таблице оффсетов count_emails = data_read(logFile,0x20+data_read(logFile,offset_to_OT+4,'DWORDl'),'DWORDl') #Количество переписок db_type = '' for i in range(count_emails): offset_end_mail = data_read(logFile,offset_to_OT+end_id_mail*4,'DWORDl') # оффсет до последнего мыла mail_data_id1,mail_data_id2 = data_read(logFile,offset_end_mail+4,'DWORDl'),data_read(logFile,offset_end_mail+8,'DWORDl') if find_mra_sign(logFile,offset_end_mail+0x1C0) and db_type == '':#если нашлась сигнатура mrahistory_ db_type = 'icq' elif find_mra_sign(logFile,offset_end_mail+0x194) and db_type == '': db_type = 'mra' else: pass if find_mra_sign(logFile,offset_end_mail+set_offset(db_type)): id1,id2 = data_read(logFile,offset_end_mail+4+0x24,'DWORDl'),data_read(logFile,offset_end_mail+8+0x24,'DWORDl') logFile.seek(offset_end_mail+4+set_offset(db_type)+12) #Оффсет до ников(емэйлов) splitUinLine = logFile.readline()[::2].split("\x00")[0].split("_") #Получаем UIN'ы myUin,hisUin = splitUinLine[0],splitUinLine[1] id_message = id1 while id_message: offset = data_read(logFile,offset_to_OT+4*id_message,'DWORDl') prev_id,next_id,date,time,direction,text,nick = getMessage(logFile,offset,db_type) messages.append(Message(myUin,hisUin,direction,text,date,time)) id_message=prev_id end_id_mail = mail_data_id2 return messages except: print 'File open fail'
def getHeader(_logFile): _offset=0 _signature = '' try: for i in range(16): _signature += chr(data_read(_logFile,_offset,'Byte')[0]) # 'Miranda ICQ DB',0,26 _offset+=1 except: print 'Signature check fail' return 0 if _signature == 'Miranda ICQ DB'+chr(0)+chr(26): _version = data_read(_logFile,_offset,'DWORDl') #as 4 bytes, ie 1.2.3.10=0x0102030a _offset+=4 _ofsFileEnd = data_read(_logFile,_offset,'DWORDl') #оффсет до конца файла _offset+=4 _slackSpace = data_read(_logFile,_offset,'DWORDl') #a counter of the number of bytes that have been #wasted so far due to deleting structures and/or #re-making them at the end. We should compact when #this gets above a threshold _offset+=4 _contactCount = data_read(_logFile,_offset,'DWORDl') #количество контактов в цепочке, исключая пользрвателя _offset+=4 _ofsFirstContact = data_read(_logFile,_offset,'DWORDl')#оффсет до первой структуры DBContact в цепочке _offset+=4 _ofsUser = data_read(_logFile,_offset,'DWORDl') #оффсет до структуры DBContact представляющей пользователя _offset+=4 _ofsFirstModuleName = data_read(_logFile,_offset,'DWORDl')#оффсет до первой структуры DBModuleName в цепочке #print 'header:', _signature,hex(_version),hex(_ofsFileEnd),_slackSpace,_contactCount,hex(_ofsFirstContact),hex(_ofsUser),hex(_ofsFirstModuleName) return _signature,_version,_ofsFileEnd,_slackSpace,_contactCount,_ofsFirstContact,_ofsUser,_ofsFirstModuleName else: print 'Signature check fail' return 0
def parseQipHistory(file_name, messages): myUin = file_name.split(sep)[-3] try: with open(file_name, 'rb') as qhf_file: signature = data_read(qhf_file, 0x00, 'Char', 3) if not signature == 'QHF': print 'File type error' return messages version = data_read(qhf_file, 0x03, 'Byte')[0] if version not in [1, 2, 3]: print 'History version error' return messages _messages_count = data_read(qhf_file, 0x22, 'DWORD') _messages_count_check = data_read(qhf_file, 0x26, 'DWORD') if _messages_count == _messages_count_check: messages_count = _messages_count else: print 'History read error' return messages uin_len = data_read(qhf_file, 0x2c, 'Word') hisUin = data_read(qhf_file, 0x2e, 'Char', uin_len) nickname_len = data_read(qhf_file, 0x2e + uin_len, 'Word') nickname = data_read(qhf_file, 0x2e + uin_len + 2, 'Char', nickname_len) header_size = 0x2e + uin_len + 2 + nickname_len return get_messages(qhf_file, header_size, messages_count, version, myUin, hisUin, messages) except: print 'File open fail' return messages
def parseQipHistory(file_name,messages): myUin = file_name.split(sep)[-3] try: with open(file_name, 'rb') as qhf_file: signature = data_read(qhf_file, 0x00, 'Char', 3) if not signature == 'QHF': print 'File type error' return messages version = data_read(qhf_file, 0x03, 'Byte')[0] if version not in [1, 2, 3]: print 'History version error' return messages _messages_count = data_read(qhf_file, 0x22, 'DWORD') _messages_count_check = data_read(qhf_file, 0x26, 'DWORD') if _messages_count == _messages_count_check: messages_count = _messages_count else: print 'History read error' return messages uin_len = data_read(qhf_file, 0x2c, 'Word') hisUin = data_read(qhf_file, 0x2e, 'Char', uin_len) nickname_len = data_read(qhf_file, 0x2e+uin_len, 'Word') nickname = data_read(qhf_file, 0x2e+uin_len+2, 'Char', nickname_len) header_size = 0x2e+uin_len+2+nickname_len return get_messages(qhf_file,header_size,messages_count,version,myUin,hisUin,messages) except: print 'File open fail' return messages
def getContact(_logFile,_offset): _csignature = data_read(_logFile,_offset,'DWORDl') #0x43DECADE _offset+=4 _ofsNextContact = data_read(_logFile,_offset,'DWORDl') #оффсет до следующего пользователя в цепочке, 0 если #это контакт пользователя или последний котакт в цепочке _offset+=4 _ofsFirstSettings = data_read(_logFile,_offset,'DWORDl') #оффсет до первой DBContactSettings в #цепочке для этого контакта _offset+=4 _eventCount = data_read(_logFile,_offset,'DWORDl') #количество событий для этого контакта _offset+=4 _ofsFirstEvent = data_read(_logFile,_offset,'DWORDl') #оффсет до первого и последнего DBEvent в #цеопчке для этого контакта _offset+=4 _ofsLastEvent = data_read(_logFile,_offset,'DWORDl') _offset+=4 _ofsFirstUnreadEvent = data_read(_logFile,_offset,'DWORDl')#оффсет до первого(хронологически) непрочитоннаго #события в цепи, 0 если все прочитаны _offset+=4 _timestampFirstUnread = data_read(_logFile,_offset,'DWORDl')#timestamp of the event at ofsFirstUnreadEvent #print 'contact: ', hex(csignature),hex(ofsNextContact),hex(ofsFirstSettings),eventCount,hex(ofsFirstEvent),hex(ofsLastEvent),hex(ofsFirstUnreadEvent),timestampFirstUnread return _csignature,_ofsNextContact,_ofsFirstSettings,_eventCount,_ofsFirstEvent,_ofsLastEvent,_ofsFirstUnreadEvent,_timestampFirstUnread
def get_messages(_qhf_file,_offset,_messages_count,_version,_myUin,_hisUin,messages): for i in range(_messages_count): dt = UnixTimeToDataTime(data_read(_qhf_file, _offset+0x12, 'DWORD')) data_read(_qhf_file, _offset+0x1a, 'Byte')[0] direction = 'out' if data_read(_qhf_file, _offset+0x1a, 'Byte')[0]!=0 else 'in' if _version == 3: message_size_type = 'DWORD' message_text_offset = 0x23 else: message_size_type = 'Word' message_text_offset = 0x21 message_size = data_read(_qhf_file, _offset+0x1f, message_size_type) crypt_message_text = data_read(_qhf_file, _offset+message_text_offset, 'Byte', message_size) text = msg_decrypt(crypt_message_text) message = Message(_myUin,_hisUin,direction,text,dt[0],dt[1]) messages.append(message) _offset = _offset+0x23+message_size return messages
def get_messages(_qhf_file, _offset, _messages_count, _version, _myUin, _hisUin, messages): for i in range(_messages_count): dt = UnixTimeToDataTime(data_read(_qhf_file, _offset + 0x12, 'DWORD')) data_read(_qhf_file, _offset + 0x1a, 'Byte')[0] direction = 'out' if data_read(_qhf_file, _offset + 0x1a, 'Byte')[0] != 0 else 'in' if _version == 3: message_size_type = 'DWORD' message_text_offset = 0x23 else: message_size_type = 'Word' message_text_offset = 0x21 message_size = data_read(_qhf_file, _offset + 0x1f, message_size_type) crypt_message_text = data_read(_qhf_file, _offset + message_text_offset, 'Byte', message_size) text = msg_decrypt(crypt_message_text) message = Message(_myUin, _hisUin, direction, text, dt[0], dt[1]) messages.append(message) _offset = _offset + 0x23 + message_size return messages
def getUinFromSettings(_logFile,_offset): while True: #DBContactSettings #В этих структурах ищем UIN контакта _ssignature = data_read(_logFile,_offset,'DWORDl') _offset+=4 _ofsNextSettings = data_read(_logFile,_offset,'DWORDl') _offset+=4 _ofsModuleName = data_read(_logFile,_offset,'DWORDl') _offset+=4 _cbBlob = data_read(_logFile,_offset,'DWORDl') _offset+=4 _blob = '' for b in range(_cbBlob): _blob+=chr(data_read(_logFile,_offset,'Byte')[0]) _offset+=1 if _blob.find('UIN') != -1: _offset = _offset-_cbBlob+_blob.find('UIN')+4 _uin = data_read(_logFile,_offset,'DWORDl') break if not _ofsNextSettings: break _offset = _ofsNextSettings return _uin#_ssignature,_ofsNextSettings,_ofsModuleName,_cbBlob,_blob,_uin
def getMessage(_logFile,_offset,_db_type): # Заполняем структуру _message _size = data_read(_logFile,_offset,'DWORDl') #unsigned int size; _offset+=4 _prev_id = data_read(_logFile,_offset,'DWORDl') #unsigned int prev_id; _offset+=4 _next_id = data_read(_logFile,_offset,'DWORDl') #unsigned int next_id; _offset+=4 _xz1 = data_read(_logFile,_offset,'DWORDl') #unsigned int xz1; _offset+=4 _file_time = [] #FILETIME time; _file_time.append(data_read(_logFile,_offset,'DWORDl'))#DWORD dwLowDateTime; _offset+=4 _file_time.append(data_read(_logFile,_offset,'DWORDl'))#DWORD dwHighDateTime; _offset+=4 _type_message = data_read(_logFile,_offset,'DWORDl')#unsigned int type_message; _offset+=4 _direction = 'out' if data_read(_logFile,_offset,'DWORDl') == 1 else 'in'#char flag_incoming; _offset+=4 _count_nick = data_read(_logFile,_offset,'DWORDl') #unsigned int count_nick; _offset+=4 _magic_num = data_read(_logFile,_offset,'DWORDl') #unsigned int magic_num; // 0x38 _offset+=4 _count_message = data_read(_logFile,_offset,'DWORDl')#unsigned int count_message; // именно количество, не размер в байтах _offset+=4 _xz2 = data_read(_logFile,_offset,'DWORDl') #unsigned int xz2; // _offset+=4 _size_lps_rtf = data_read(_logFile,_offset,'DWORDl')#unsigned int size_lps_rtf; // байт _offset+=4 _xz3 = data_read(_logFile,_offset,'DWORDl') #unsigned int xz3; // _offset+=4 if _db_type == 'icq': _xz4 = data_read(_logFile,_offset,'DWORDl') _offset+=8 _date_time = str(FiletimeToDateTime(_file_time[0],_file_time[1])).split(' ') _date,_time = _date_time[0].replace('-','.'),_date_time[1].split('.')[0] _nick = u'' for c in range(_count_nick-1): # Читаем ник _nick +=unichr(data_read(_logFile,_offset,'Wordl')) _offset += 2 # Указатель теперь указывает на сообщение в unicode if data_read(_logFile,_offset,'Wordl') == 0 and _type_message == 0x11: _count_message = data_read(_logFile,_offset+1,'DWORDl')/2+1 _offset += 3 _text = u'' for c in range(_count_message): _text += unichr(data_read(_logFile,_offset,'Wordl')) _offset+=2 return _prev_id,_next_id,_date,_time,_direction,_text,_nick