extraction.go 3.77 KB
package main

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"

	"github.com/dgrijalva/jwt-go"
	"github.com/jmoiron/sqlx"
	"github.com/labstack/echo/v4"

	_ "github.com/mattn/go-sqlite3"
)

func (app *App) PostExtractions(c echo.Context) error {
	userNo := c.Get("user").(*jwt.Token).Claims.(*AuthClaims).UserNo

	form, err := c.FormFile("file")
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "Unknown error")
	}

	src, err := form.Open()
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "Unknown error")
	}
	defer src.Close()

	file, err := ioutil.TempFile("", "extraction")
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "Unknown error")
	}
	defer os.Remove(file.Name())

	if _, err := io.Copy(file, src); err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "Unknown error")
	}
	file.Close()

	db, err := sqlx.Connect("sqlite3", file.Name())
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "Could not open db file")
	}
	defer db.Close()

	tx, err := app.db.Beginx()
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "Unknown error")
	}

	res, _ := tx.Exec("INSERT INTO extractions (`owner`) VALUES (?)", userNo)
	extNo, _ := res.LastInsertId()

	rows, err := db.Queryx("SELECT * FROM calllog")
	if err == nil {
		for rows.Next() {
			vals, _ := rows.SliceScan()
			_, err = tx.Exec("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?)", append([]interface{}{extNo}, vals...)...)
		}
	}

	sql := `SELECT
		a.packagename, a.name, a.version, a.wifiusage, a.cellularusage,
		u.lasttimeused, u.totaltimeforeground
	FROM AppInfo a JOIN AppUsageYear u ON a.packagename=u.packagename`
	rows, err = db.Queryx(sql)
	if err == nil {
		for rows.Next() {
			vals, _ := rows.SliceScan()
			tx.Exec("INSERT INTO apps VALUES (?, ?, ?, ?, ?, ?, ?, ?)", append([]interface{}{extNo}, vals...)...)
		}
	}

	rows, err = db.Queryx("SELECT mid, type, address, body, date FROM sms")
	if err == nil {
		idxName := fmt.Sprintf("messages-%d", extNo)
		app.es.CreateIndex(idxName).Body(`{
			"settings": {
				"analysis": {
					"analyzer": {
						"default": {
							"type": "custom",
							"tokenizer": "nori_tokenizer"
						}
					}
				}
			}
		}`).Do(context.Background())

		for rows.Next() {
			vals, _ := rows.SliceScan()
			tx.Exec("INSERT INTO messages VALUES (?, ?, ?, ?, ?, ?)", append([]interface{}{extNo}, vals...)...)
			app.es.Index().Index(idxName).Id(fmt.Sprint(vals[0])).BodyJson(echo.Map{"content": string(vals[3].([]byte))}).Do(context.Background())
		}
	}

	rows, err = db.Queryx("SELECT PID, UID, PPID, STIME, TIME, CMD FROM process")
	if err == nil {

		for rows.Next() {
			vals, _ := rows.SliceScan()
			tx.Exec("INSERT INTO processes VALUES (?, ?, ?, ?, ?, ?, ?)", append([]interface{}{extNo}, vals...)...)
		}
	}

	/*alarms := map[string]Alarm{}
	rows, _ = db.Queryx("SELECT * FROM alarm ORDER BY TIME")

	for rows.Next() {
		var tm string
		var typ string
		var detail string

		rows.Scan(&tm, &typ, &detail)

		detail = detail[strings.Index(detail, "{")+1 : strings.Index(detail, "}")]
		s := strings.Split(detail, " ")
		timestamp, _ := strconv.ParseInt(s[4], 10, 64)
		timestamp /= 1000

		if _, ok := alarms[s[0]]; !ok {
			alarms[s[0]] = Alarm{ID: s[0], When: time.Unix(timestamp, 0)}
		}

		when, _ := time.Parse("2006-01-02 15:04:05", tm)
		alarm := alarms[s[0]]
		alarm.History = append(alarms[s[0]].History, AlarmHistory{
			Type: typ,
			When: when,
		})
		alarms[s[0]] = alarm
	}

	for _, v := range alarms {
		tx.Exec("INSERT INTO alarms VALUES (?, ?, ?)", extNo, v.ID, v.When)

		for _, h := range v.History {
			tx.Exec("INSERT INTO alarm_histories VALUES (?, ?, ?, ?)", extNo, v.ID, h.Type, h.When)
		}
	}*/

	tx.Commit()

	return c.NoContent(http.StatusNoContent)
}