func init() { config.RegisterFunc(&logConfig, func() { if logConfig.LogDebug { Std.SetLevel(LDebug) } else { // Check if we should send errors to the admin email admin := mail.AdminEmail() from := mail.DefaultFrom() server := mail.DefaultServer() if admin != "" && server != "" { writer := NewSmtpWriter(LError, server, from, admin) Std.AddWriter(writer) } } }) }
func (app *App) logError(ctx *Context, err interface{}) { skip, stackSkip, _, _ := runtimeutil.GetPanic() var buf bytes.Buffer if ctx.R != nil { buf.WriteString("Panic serving ") buf.WriteString(ctx.R.Method) buf.WriteByte(' ') buf.WriteString(ctx.R.Host) buf.WriteString(ctx.R.URL.Path) if rq := ctx.R.URL.RawQuery; rq != "" { buf.WriteByte('?') buf.WriteString(rq) } if rf := ctx.R.URL.Fragment; rf != "" { buf.WriteByte('#') buf.WriteString(rf) } buf.WriteByte(' ') buf.WriteString(ctx.RemoteAddress()) } else { buf.WriteString("Panic") } elapsed := ctx.Elapsed() fmt.Fprintf(&buf, " (after %s): %v\n", elapsed, err) stack := runtimeutil.FormatStack(stackSkip) location, code := runtimeutil.FormatCaller(skip, 5, true, true) if location != "" { buf.WriteString("\n At ") buf.WriteString(location) if code != "" { buf.WriteByte('\n') buf.WriteString(code) buf.WriteByte('\n') } } if stack != "" { buf.WriteString("\nStack:\n") buf.WriteString(stack) } req := "" if ctx.R != nil { dump, derr := httputil.DumpRequest(ctx.R, true) if derr == nil { // This cleans up empty lines and replaces \r\n with \n req = stringutil.Lines(string(dump), 0, 10000, true) buf.WriteString("\nRequest:\n") buf.WriteString(req) } // Check if there are any attached files that we might // want to send in an email if !app.cfg.Debug && mail.AdminEmail() != "" { ctx.R.ParseMultipartForm(32 << 20) // 32 MiB, as stdlib if form := ctx.R.MultipartForm; form != nil { var count int var attachments []*mail.Attachment var message bytes.Buffer if len(form.File) > 0 { for k, v := range form.File { for _, file := range v { f, err := file.Open() if err != nil { fmt.Fprintf(&message, "%s => error %s", k, err) continue } attachment, err := mail.NewAttachment(file.Filename, f) attachment.ContentType = file.Header.Get("Content-Type") f.Close() if err != nil { fmt.Fprintf(&message, "%s => error %s", k, err) continue } count++ fmt.Fprintf(&message, "%s => %s (%s)", k, attachment.Name, attachment.ContentType) attachments = append(attachments, attachment) } } fmt.Fprintf(&message, "\nError:\n%s", buf.String()) host, _ := os.Hostname() from := mail.DefaultFrom() if from == "" { from = fmt.Sprintf("errors@%s", host) } msg := &mail.Message{ From: from, To: mail.Admin, Subject: fmt.Sprintf("Panic with %d attached files on %s", count, host), TextBody: message.String(), Attachments: attachments, } ctx.SendMail("", nil, msg) } } } } ctx.Logger().Error(buf.String()) if app.cfg.Debug { app.errorPage(ctx, elapsed, skip, stackSkip, req, err) } else { app.handleHTTPError(ctx, "Internal Server Error", http.StatusInternalServerError) } }
func forgotHandler(ctx *app.Context) { d := data(ctx) if !d.allowDirectSignIn() { ctx.NotFound("") return } var user User var isEmail bool var sent bool var fields struct { Username string `form:",singleline,label=Username or Email"` ValidateUsername func(*app.Context) error } fields.ValidateUsername = func(c *app.Context) error { username := Normalize(fields.Username) isEmail = strings.Contains(username, "@") var field string if isEmail { field = "User.NormalizedEmail" } else { field = "User.NormalizedUsername" } userVal, userIface := newEmptyUser(ctx) ok := c.Orm().MustOne(orm.Eq(field, username), userIface) if !ok { if isEmail { return i18n.Errorf("address %q does not belong to any registered user", username) } return i18n.Errorf("username %q does not belong to any registered user", username) } user = getUserValue(userVal, "User").(User) if user.Email == "" { return i18n.Errorf("username %q does not have any registered emails", username) } return nil } f := form.New(ctx, &fields) if f.Submitted() && f.IsValid() { se, err := ctx.App().EncryptSigner(Salt) if err != nil { panic(err) } values := make(url.Values) values.Add("u", strconv.FormatInt(user.Id(), 36)) values.Add("t", strconv.FormatInt(time.Now().Unix(), 36)) values.Add("n", stringutil.Random(64)) payload := values.Encode() p, err := se.EncryptSign([]byte(payload)) if err != nil { panic(err) } abs := ctx.URL() reset := fmt.Sprintf("%s://%s%s?p=%s", abs.Scheme, abs.Host, ctx.MustReverse(ResetHandlerName), p) data := map[string]interface{}{ "URL": reset, } from := mail.DefaultFrom() if from == "" { from = fmt.Sprintf("no-reply@%s", abs.Host) } msg := &mail.Message{ To: user.Email, From: from, Subject: fmt.Sprintf(ctx.T("Reset your %s password"), d.opts.SiteName), } ctx.MustSendMail("reset_password.txt", data, msg) sent = true } data := map[string]interface{}{ "ForgotForm": f, "IsEmail": isEmail, "Sent": sent, "User": user, } ctx.MustExecute(ForgotTemplateName, data) }