func userSetPassword(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() c := context.New(r) u := user.Current(c, db) if !u.Validate(r.FormValue("oldpassword")) { return handler.NewError(nil, 400, "Old password incorrect!") } newPass := r.FormValue("password") if newPass != r.FormValue("repeatpassword") { return handler.NewError(nil, 400, "New password doesn't match!") } if len(newPass) > 100 { return handler.NewError(nil, 400, "Password length over 100. Seriously?!") } u.SetPassword(newPass) if err := db.C("users").UpdateId(u.Id, u); err != nil { return handler.NewError(err, 500, "Error updating user password!") } return nil }
// download provides the requested apk by the given bson.ObjectId func download(w http.ResponseWriter, r *http.Request) *handler.Error { var ( apk Apk buf bytes.Buffer ) db := datastore.New() defer db.Close() q := bson.M{"_id": bson.ObjectIdHex(r.FormValue("id"))} err := db.C("apks").Find(q).One(&apk) if err != nil { return handler.NewError(err, 404, "No record of apk.") } file, err := db.FS().OpenId(apk.FileId) if err != nil { return handler.NewError(err, 404, "No such apk.") } io.Copy(&buf, file) filename := fmt.Sprintf("%s-%s.apk", apk.Badging.ApplicationLabel, apk.Time) w.Header().Set("Content-Type", "application/vnd.android.package-archive") w.Header().Set("Content-Disposition", "attachment;filename="+filename) w.Write(buf.Bytes()) return nil }
// icon retrieves a previously saved apk icon. func icon(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() id := mux.Vars(r)["iconId"] if id == "" { w.Header().Set("Content-type", "image/png") w.Write([]byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 8, 215, 99, 96, 96, 96, 96, 0, 0, 0, 5, 0, 1, 94, 243, 42, 58, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130}) return nil } file, err := db.FS().OpenId(bson.ObjectIdHex(id)) if err != nil { return handler.NewError(err, 404, "No such icon.") } var buf bytes.Buffer io.Copy(&buf, file) // TODO set content type correctly w.Header().Set("Content-type", "image/png") w.Write(buf.Bytes()) return nil }
func ProjectById(u *user.User, id bson.ObjectId) (project *Project) { db := datastore.New() defer db.Close() q := bson.M{"_id": id, "userids": u.Id} if err := db.C("projects").Find(q).One(&project); err != nil { panic(err) } project.LoadLastApk(db) return }
func userCurrent(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() c := context.New(r) u := user.Current(c, db) m := bson.M{"Name": u.Name, "Email": u.Email} render.Json(w, m) return nil }
func projectsByUser(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() c := context.New(r) u := user.Current(c, db) projects := ProjectsByUser(u, db) render.Json(w, projects) return nil }
func projectHistory(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() c := context.New(r) u := user.Current(c, db) id := bson.ObjectIdHex(mux.Vars(r)["projectId"]) project := ProjectById(u, id) render.Json(w, project.History(db)) return nil }
func apkById(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() apkId := bson.ObjectIdHex(mux.Vars(r)["id"]) var apk *Apk // TODO confirm user has access to apk if err := db.C("apks").FindId(apkId).One(&apk); err != nil { return handler.NewError(err, 500, "Failed to locate apk.") } render.Json(w, apk) return nil }
func errorsByApkId(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() apkId := bson.ObjectIdHex(mux.Vars(r)["apkId"]) var reports []*Report q := bson.M{"apkid": apkId} if err := db.C("reports").Find(q).All(&reports); err != nil { return handler.NewError(err, 500, "Error querying for apk reports.") } render.Json(w, groupErrors(reports)) return nil }
func userSetProfile(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() c := context.New(r) u := user.Current(c, db) u.Name = r.FormValue("name")[:100] u.Email = r.FormValue("email")[:100] if err := db.C("users").UpdateId(u.Id, u); err != nil { return handler.NewError(err, 500, "Error updating user profile") } return nil }
// report is a web handler that saves ACRA reports. func report(w http.ResponseWriter, r *http.Request) *handler.Error { if err := r.ParseForm(); err != nil { return handler.NewError(err, 500, "Error parsing form data.") } db := datastore.New() defer db.Close() // find apk var apk *Apk name := r.FormValue("PACKAGE_NAME") vc := r.FormValue("APP_VERSION_CODE") // TODO use user submitted formid that identifies user with public hash for locating correct package q := bson.M{"badging.package.name": name, "badging.package.versionCode": vc} if err := db.C("apks").Find(q).Sort("-time").One(&apk); err != nil { // return 200 so acra doesn't keep resubmitting the report return handler.NewError(err, 200, fmt.Sprintf("No apk by given name and version code found: NAME %s VC %s", name, vc)) } // save report using generic map to keep values not accounted for in Report struct. m := bson.M{} for k, v := range r.Form { if len(v) == 1 { m[k] = v[0] } } reportId := bson.NewObjectId() m["_id"] = reportId m["apkid"] = apk.Id m["time"] = time.Now() if err := db.C("reports").Insert(m); err != nil { return handler.NewError(err, 500, "Error inserting new report") } apk.ReportIds = append([]bson.ObjectId{reportId}, apk.ReportIds...) if err := db.C("apks").UpdateId(apk.Id, apk); err != nil { return handler.NewError(err, 500, "Error updating apk reportids") } // TODO send email notify if desired by user return nil }
func main() { flag.Parse() render.Cache = *cache handler.Debug = *debug datastore.DBHost = *dbhost datastore.DBName = *dbname if *adduser != "" { u := user.New() u.Email = *adduser u.SetPassword("qwerty") db := datastore.New() defer db.Close() if err := db.C("users").Insert(u); err != nil { log.Fatal(err) } log.Print("user added, password is `qwerty`.") } else { if *memprofile != "" { c := make(chan os.Signal) signal.Notify(c) go func() { for sig := range c { log.Printf("Received %v", sig) f, err := os.Create(*memprofile) if err != nil { log.Fatal(err) } pprof.WriteHeapProfile(f) f.Close() } }() } log.Fatal(http.ListenAndServe("localhost:8090", nil)) } }
// ProjectByName finds a project for the given user by the given name // or creates a new one if one does not exist. func ProjectByName(u *user.User, name string) *Project { var projects []Project db := datastore.New() defer db.Close() q := bson.M{"userids": u.Id} if err := db.C("projects").Find(q).All(&projects); err != nil { panic(err) } for _, project := range projects { if project.PackageName == name { return &project } } // new project if one does not exist project := &Project{Id: bson.NewObjectId(), PackageName: name} project.UserIds = append(project.UserIds, u.Id) return project }
func exportCSV(w http.ResponseWriter, r *http.Request) *handler.Error { w.Header().Set("Content-Type", "text/csv") w.Header().Set("Content-Disposition", "attachment;filename=export.csv") wrtr := csv.NewWriter(w) var sampleReport Report csvHeaders := listFields(sampleReport) wrtr.Write(csvHeaders) db := datastore.New() defer db.Close() var reports []*Report q := bson.M{"apkid": bson.ObjectIdHex(r.FormValue("id"))} if err := db.C("reports").Find(q).All(&reports); err != nil { return handler.NewError(err, 500, "Error querying for apk reports.") } for _, report := range reports { var record []string s := reflect.ValueOf(report).Elem() t := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) if ignoreField(t.Field(i).Name) { continue } record = append(record, f.String()) } wrtr.Write(record) } return nil }
func errorDetails(w http.ResponseWriter, r *http.Request) *handler.Error { db := datastore.New() defer db.Close() // get session user // c := context.New(r) // u := user.Current(c, db) apkId := mux.Vars(r)["apkId"] reportId := mux.Vars(r)["reportId"] var report *Report db.C("reports").FindId(bson.ObjectIdHex(reportId)).One(&report) // get info from related reports to attach here var reports []*Report q := bson.M{"apkid": bson.ObjectIdHex(apkId)} // TODO confirm user has access to project if err := db.C("reports").Find(q).All(&reports); err != nil { return handler.NewError(err, 500, "Error querying for apk reports.") } attachGroupDetails(report, reports) render.Json(w, report) return nil }
// upload is a web handler for receiving an apk. func upload(w http.ResponseWriter, r *http.Request) *handler.Error { // dont use memory for holding apk if err := r.ParseMultipartForm(0); err != nil { return handler.NewError(err, 500, "Unable to parse multipart form.") } f, _, err := r.FormFile("apk") if err != nil { return handler.NewError(err, 500, "Form file \"apk\" does not exist") } // dump badging and locate appropriate icon name within apk m := dumpBadging(f.(*os.File).Name()) k := fmt.Sprintf("application-icon-%s", m["densities"].([]interface{})[0]) res := m[k].(string) // locate tmp file and extract icon fi, err := f.(*os.File).Stat() if err != nil { return handler.NewError(err, 500, "Can't stat file.") } zr, err := zip.NewReader(f, fi.Size()) if err != nil { return handler.NewError(err, 500, "Not a valid zip archive") } icon := zipReadBytes(zr, res) // Link current user to package name, save badging, apk file, and icon file. db := datastore.New() defer db.Close() u := user.Current(context.New(r), db) apkFile, err := db.FS().Create("") if err != nil { return handler.NewError(err, 500, "Can't save apk") } defer apkFile.Close() io.Copy(apkFile, f) iconFile, err := db.FS().Create("") if err != nil { return handler.NewError(err, 500, "Can't save icon") } defer iconFile.Close() iconFile.Write(icon) // using bson.M to store all badging values, including those not specified in struct apkId := bson.NewObjectId() apkName := m["package"].(map[string]interface{})["name"].(string) apkM := bson.M{ "_id": apkId, "fileid": apkFile.Id(), "iconid": iconFile.Id(), "time": time.Now(), "badging": m, } if err = db.C("apks").Insert(apkM); err != nil { return handler.NewError(err, 500, "Error inserting apk info.") } project := ProjectByName(u, apkName) project.ApkIds = append([]bson.ObjectId{apkId}, project.ApkIds...) if _, err = db.C("projects").UpsertId(project.Id, project); err != nil { return handler.NewError(err, 500, "Error upserting project.") } http.Redirect(w, r, "/console/index", 302) return nil }