2021-02-20 14:03:54 +00:00
package shroom
import (
2021-09-29 14:56:17 +00:00
"bytes"
2021-02-20 14:03:54 +00:00
"errors"
"fmt"
2022-04-02 16:58:57 +00:00
"github.com/bouncepaw/mycorrhiza/backlinks"
2022-02-06 13:09:56 +00:00
"github.com/bouncepaw/mycorrhiza/files"
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/hyphae"
2022-02-04 17:04:39 +00:00
"github.com/bouncepaw/mycorrhiza/mimetype"
2022-02-06 13:09:56 +00:00
"github.com/bouncepaw/mycorrhiza/user"
2021-07-02 08:29:55 +00:00
"io"
2021-02-20 14:03:54 +00:00
"log"
"mime/multipart"
"os"
"path/filepath"
)
2022-02-19 08:26:38 +00:00
func historyMessageForTextUpload ( h hyphae . Hypha , userMessage string ) string {
2022-02-04 17:04:39 +00:00
var verb string
2022-02-04 14:56:28 +00:00
switch h . ( type ) {
case * hyphae . EmptyHypha :
2022-02-04 17:04:39 +00:00
verb = "Create"
2022-02-04 14:56:28 +00:00
default :
2022-02-04 17:04:39 +00:00
verb = "Edit"
2021-02-20 14:03:54 +00:00
}
2022-02-04 17:04:39 +00:00
if userMessage == "" {
return fmt . Sprintf ( "%s ‘ %s’ " , verb , h . CanonicalName ( ) )
2021-06-14 00:38:43 +00:00
}
2022-02-04 17:04:39 +00:00
return fmt . Sprintf ( "%s ‘ %s’ : %s" , verb , h . CanonicalName ( ) , userMessage )
}
2021-06-14 00:38:43 +00:00
2022-02-19 08:26:38 +00:00
func writeTextToDisk ( h hyphae . ExistingHypha , data [ ] byte , hop * history . Op ) error {
2022-02-26 06:42:54 +00:00
if err := hyphae . WriteToMycoFile ( h , data ) ; err != nil {
2022-02-04 17:04:39 +00:00
return err
}
2022-02-19 08:26:38 +00:00
hop . WithFiles ( h . TextFilePath ( ) )
2022-02-04 17:25:07 +00:00
2022-02-04 17:04:39 +00:00
return nil
}
// UploadText edits the hypha's text part and makes a history record about that.
2022-02-20 09:27:30 +00:00
func UploadText ( h hyphae . Hypha , data [ ] byte , userMessage string , u * user . User ) error {
2022-02-19 16:42:32 +00:00
hop := history .
2022-02-04 17:04:39 +00:00
Operation ( history . TypeEditText ) .
2022-02-04 17:25:07 +00:00
WithMsg ( historyMessageForTextUpload ( h , userMessage ) ) .
WithUser ( u )
2022-02-04 17:04:39 +00:00
// Privilege check
if ! u . CanProceed ( "upload-text" ) {
rejectEditLog ( h , u , "no rights" )
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return errors . New ( "ui.act_no_rights" )
2021-02-20 14:03:54 +00:00
}
2022-02-04 17:04:39 +00:00
// Hypha name exploit check
if ! hyphae . IsValidName ( h . CanonicalName ( ) ) {
// We check for the name only. I suppose the filepath would be valid as well.
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return errors . New ( "invalid hypha name" )
2022-02-04 17:04:39 +00:00
}
2022-06-11 09:36:45 +00:00
oldText , err := hyphae . FetchMycomarkupFile ( h )
if err != nil {
hop . Abort ( )
return err
}
2022-02-04 17:04:39 +00:00
// Empty data check
2022-06-11 09:36:45 +00:00
if len ( bytes . TrimSpace ( data ) ) == 0 && len ( oldText ) == 0 { // if nothing but whitespace
hop . Abort ( )
return nil
2021-02-20 14:03:54 +00:00
}
2022-02-04 17:04:39 +00:00
// At this point, we have a savable user-generated Mycomarkup document. Gotta save it.
switch h := h . ( type ) {
case * hyphae . EmptyHypha :
2022-02-19 08:26:38 +00:00
H := hyphae . ExtendEmptyToTextual ( h , filepath . Join ( files . HyphaeDir ( ) , h . CanonicalName ( ) + ".myco" ) )
2022-02-04 17:25:07 +00:00
err := writeTextToDisk ( H , data , hop )
2022-02-04 17:04:39 +00:00
if err != nil {
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return err
2022-02-04 17:04:39 +00:00
}
2022-02-04 17:25:07 +00:00
hyphae . Insert ( H )
2022-02-26 06:42:54 +00:00
backlinks . UpdateBacklinksAfterEdit ( H , "" )
2022-02-19 08:26:38 +00:00
case * hyphae . MediaHypha :
// TODO: that []byte(...) part should be removed
2022-04-02 08:09:37 +00:00
if bytes . Equal ( data , [ ] byte ( oldText ) ) {
2022-02-19 08:26:38 +00:00
// No changes! Just like cancel button
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return nil
2022-02-19 08:26:38 +00:00
}
err = writeTextToDisk ( h , data , hop )
if err != nil {
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return err
2022-02-19 08:26:38 +00:00
}
backlinks . UpdateBacklinksAfterEdit ( h , oldText )
case * hyphae . TextualHypha :
2022-06-06 14:41:33 +00:00
oldText , err := hyphae . FetchMycomarkupFile ( h )
2022-02-04 17:04:39 +00:00
if err != nil {
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return err
2022-02-04 17:04:39 +00:00
}
// TODO: that []byte(...) part should be removed
2022-04-02 08:09:37 +00:00
if bytes . Equal ( data , [ ] byte ( oldText ) ) {
2022-02-04 17:04:39 +00:00
// No changes! Just like cancel button
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return nil
2022-02-04 17:04:39 +00:00
}
2022-02-04 17:25:07 +00:00
err = writeTextToDisk ( h , data , hop )
2022-02-04 17:04:39 +00:00
if err != nil {
2022-02-19 16:42:32 +00:00
hop . Abort ( )
return err
2022-02-04 17:04:39 +00:00
}
backlinks . UpdateBacklinksAfterEdit ( h , oldText )
}
2022-02-19 16:42:32 +00:00
hop . Apply ( )
return nil
2021-02-20 14:03:54 +00:00
}
2022-02-19 08:26:38 +00:00
func historyMessageForMediaUpload ( h hyphae . Hypha , mime string ) string {
2022-02-06 13:09:56 +00:00
return fmt . Sprintf ( "Upload media for ‘ %s’ with type ‘ %s’ " , h . CanonicalName ( ) , mime )
}
// writeMediaToDisk saves the given data with the given mime type for the given hypha to the disk and returns the path to the saved file and an error, if any.
2022-02-19 08:26:38 +00:00
func writeMediaToDisk ( h hyphae . Hypha , mime string , data [ ] byte ) ( string , error ) {
2021-02-20 14:03:54 +00:00
var (
2022-02-06 13:09:56 +00:00
ext = mimetype . ToExtension ( mime )
// That's where the file will go
uploadedFilePath = filepath . Join ( files . HyphaeDir ( ) , h . CanonicalName ( ) + ext )
2021-02-20 14:03:54 +00:00
)
2022-02-06 13:09:56 +00:00
if err := os . MkdirAll ( filepath . Dir ( uploadedFilePath ) , 0777 ) ; err != nil {
return uploadedFilePath , err
2021-02-20 14:03:54 +00:00
}
2022-02-06 13:09:56 +00:00
if err := os . WriteFile ( uploadedFilePath , data , 0666 ) ; err != nil {
return uploadedFilePath , err
2021-02-20 14:03:54 +00:00
}
2022-02-06 13:09:56 +00:00
return uploadedFilePath , nil
}
2021-02-20 14:03:54 +00:00
2022-02-06 13:09:56 +00:00
// UploadBinary edits the hypha's media part and makes a history record about that.
2022-02-20 09:27:30 +00:00
func UploadBinary ( h hyphae . Hypha , mime string , file multipart . File , u * user . User ) error {
2021-02-20 14:03:54 +00:00
2022-02-06 13:09:56 +00:00
// Privilege check
if ! u . CanProceed ( "upload-binary" ) {
2022-02-26 07:33:09 +00:00
rejectUploadMediaLog ( h , u , "no rights" )
2022-02-19 16:42:32 +00:00
return errors . New ( "ui.act_no_rights" )
2021-02-20 14:03:54 +00:00
}
2022-02-06 13:09:56 +00:00
// Hypha name exploit check
if ! hyphae . IsValidName ( h . CanonicalName ( ) ) {
// We check for the name only. I suppose the filepath would be valid as well.
2022-02-19 16:42:32 +00:00
return errors . New ( "invalid hypha name" )
2021-02-20 14:03:54 +00:00
}
2022-02-06 13:09:56 +00:00
data , err := io . ReadAll ( file )
if err != nil {
2022-02-19 16:42:32 +00:00
return err
2021-02-20 14:03:54 +00:00
}
2022-02-06 13:09:56 +00:00
// Empty data check
if len ( data ) == 0 {
2022-02-19 16:42:32 +00:00
return errors . New ( "No data passed" )
2021-02-20 14:03:54 +00:00
}
2022-02-06 13:09:56 +00:00
// At this point, we have a savable media document. Gotta save it.
2022-02-04 14:56:28 +00:00
2022-02-06 13:09:56 +00:00
uploadedFilePath , err := writeMediaToDisk ( h , mime , data )
if err != nil {
2022-02-19 16:42:32 +00:00
return err
2022-02-06 13:09:56 +00:00
}
switch h := h . ( type ) {
2022-02-04 14:56:28 +00:00
case * hyphae . EmptyHypha :
2022-02-19 08:26:38 +00:00
H := hyphae . ExtendEmptyToMedia ( h , uploadedFilePath )
2022-02-06 13:09:56 +00:00
hyphae . Insert ( H )
2022-02-19 08:26:38 +00:00
case * hyphae . TextualHypha :
hyphae . Insert ( hyphae . ExtendTextualToMedia ( h , uploadedFilePath ) )
case * hyphae . MediaHypha : // If this is not the first media the hypha gets
prevFilePath := h . MediaFilePath ( )
if prevFilePath != uploadedFilePath {
if err := history . Rename ( prevFilePath , uploadedFilePath ) ; err != nil {
2022-02-19 16:42:32 +00:00
return err
2022-02-06 13:09:56 +00:00
}
2022-02-19 08:26:38 +00:00
log . Printf ( "Move ‘ %s’ to ‘ %s’ \n" , prevFilePath , uploadedFilePath )
h . SetMediaFilePath ( uploadedFilePath )
2022-02-04 14:56:28 +00:00
}
2021-02-20 14:03:54 +00:00
}
2022-02-04 14:56:28 +00:00
2022-02-19 16:42:32 +00:00
history .
Operation ( history . TypeEditBinary ) .
WithMsg ( historyMessageForMediaUpload ( h , mime ) ) .
WithUser ( u ) .
WithFiles ( uploadedFilePath ) .
Apply ( )
return nil
2021-10-27 05:43:36 +00:00
}