github.com/topsteplocal/gophish@v0.6.0/models/page.go (about)

     1  package models
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/PuerkitoBio/goquery"
     9  	log "github.com/gophish/gophish/logger"
    10  )
    11  
    12  // Page contains the fields used for a Page model
    13  type Page struct {
    14  	Id                 int64     `json:"id" gorm:"column:id; primary_key:yes"`
    15  	UserId             int64     `json:"-" gorm:"column:user_id"`
    16  	Name               string    `json:"name"`
    17  	HTML               string    `json:"html" gorm:"column:html"`
    18  	CaptureCredentials bool      `json:"capture_credentials" gorm:"column:capture_credentials"`
    19  	CapturePasswords   bool      `json:"capture_passwords" gorm:"column:capture_passwords"`
    20  	RedirectURL        string    `json:"redirect_url" gorm:"column:redirect_url"`
    21  	ModifiedDate       time.Time `json:"modified_date"`
    22  }
    23  
    24  // ErrPageNameNotSpecified is thrown if the name of the landing page is blank.
    25  var ErrPageNameNotSpecified = errors.New("Page Name not specified")
    26  
    27  // parseHTML parses the page HTML on save to handle the
    28  // capturing (or lack thereof!) of credentials and passwords
    29  func (p *Page) parseHTML() error {
    30  	d, err := goquery.NewDocumentFromReader(strings.NewReader(p.HTML))
    31  	if err != nil {
    32  		return err
    33  	}
    34  	forms := d.Find("form")
    35  	forms.Each(func(i int, f *goquery.Selection) {
    36  		// We always want the submitted events to be
    37  		// sent to our server
    38  		f.SetAttr("action", "")
    39  		if p.CaptureCredentials {
    40  			// If we don't want to capture passwords,
    41  			// find all the password fields and remove the "name" attribute.
    42  			if !p.CapturePasswords {
    43  				inputs := f.Find("input")
    44  				inputs.Each(func(j int, input *goquery.Selection) {
    45  					if t, _ := input.Attr("type"); strings.EqualFold(t, "password") {
    46  						input.RemoveAttr("name")
    47  					}
    48  				})
    49  			}
    50  		} else {
    51  			// Otherwise, remove the name from all
    52  			// inputs.
    53  			inputFields := f.Find("input")
    54  			inputFields.Each(func(j int, input *goquery.Selection) {
    55  				input.RemoveAttr("name")
    56  			})
    57  		}
    58  	})
    59  	p.HTML, err = d.Html()
    60  	return err
    61  }
    62  
    63  // Validate ensures that a page contains the appropriate details
    64  func (p *Page) Validate() error {
    65  	if p.Name == "" {
    66  		return ErrPageNameNotSpecified
    67  	}
    68  	// If the user specifies to capture passwords,
    69  	// we automatically capture credentials
    70  	if p.CapturePasswords && !p.CaptureCredentials {
    71  		p.CaptureCredentials = true
    72  	}
    73  	return p.parseHTML()
    74  }
    75  
    76  // GetPages returns the pages owned by the given user.
    77  func GetPages(uid int64) ([]Page, error) {
    78  	ps := []Page{}
    79  	err := db.Where("user_id=?", uid).Find(&ps).Error
    80  	if err != nil {
    81  		log.Error(err)
    82  		return ps, err
    83  	}
    84  	return ps, err
    85  }
    86  
    87  // GetPage returns the page, if it exists, specified by the given id and user_id.
    88  func GetPage(id int64, uid int64) (Page, error) {
    89  	p := Page{}
    90  	err := db.Where("user_id=? and id=?", uid, id).Find(&p).Error
    91  	if err != nil {
    92  		log.Error(err)
    93  	}
    94  	return p, err
    95  }
    96  
    97  // GetPageByName returns the page, if it exists, specified by the given name and user_id.
    98  func GetPageByName(n string, uid int64) (Page, error) {
    99  	p := Page{}
   100  	err := db.Where("user_id=? and name=?", uid, n).Find(&p).Error
   101  	if err != nil {
   102  		log.Error(err)
   103  	}
   104  	return p, err
   105  }
   106  
   107  // PostPage creates a new page in the database.
   108  func PostPage(p *Page) error {
   109  	err := p.Validate()
   110  	if err != nil {
   111  		log.Error(err)
   112  		return err
   113  	}
   114  	// Insert into the DB
   115  	err = db.Save(p).Error
   116  	if err != nil {
   117  		log.Error(err)
   118  	}
   119  	return err
   120  }
   121  
   122  // PutPage edits an existing Page in the database.
   123  // Per the PUT Method RFC, it presumes all data for a page is provided.
   124  func PutPage(p *Page) error {
   125  	err := p.Validate()
   126  	err = db.Where("id=?", p.Id).Save(p).Error
   127  	if err != nil {
   128  		log.Error(err)
   129  	}
   130  	return err
   131  }
   132  
   133  // DeletePage deletes an existing page in the database.
   134  // An error is returned if a page with the given user id and page id is not found.
   135  func DeletePage(id int64, uid int64) error {
   136  	err = db.Where("user_id=?", uid).Delete(Page{Id: id}).Error
   137  	if err != nil {
   138  		log.Error(err)
   139  	}
   140  	return err
   141  }