Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions lib/api/io/exportHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ func GetExport(ctx *fiber.Ctx, exportHandler *io.ExportEtherpad, settings *setti
typesToExport := []string{
"pdf", "doc", "docx", "txt", "html", "odt", "etherpad",
}
externalTypes := []string{
"odt",
}
// All formats are now supported internally, no external tools needed
externalTypes := []string{}

if !slices.Contains(typesToExport, exportType) {
return ctx.Status(400).SendString("Invalid export type")
Expand Down
4 changes: 4 additions & 0 deletions lib/db/MySQLDB.go
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,10 @@ func NewMySQLDB(options MySQLOptions) (*MysqlDB, error) {
return nil, err
}

// Set connection pool limits to avoid "too many connections" error
sqlDb.SetMaxOpenConns(25)
sqlDb.SetMaxIdleConns(5)

_, err = sqlDb.Exec("CREATE TABLE IF NOT EXISTS pad (id VARCHAR(255) PRIMARY KEY, data TEXT)")
if err != nil {
return nil, err
Expand Down
11 changes: 8 additions & 3 deletions lib/db/PostgresDB.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ func (d PostgresDB) GetRevision(padId string, rev int) (*db.PadSingleRevision, e

query, err := d.sqlDB.Query(retrievedSql, args...)
if err != nil {
println("Error getting revision", err)
return nil, err
}

defer query.Close()
Expand Down Expand Up @@ -452,13 +452,13 @@ func (d PostgresDB) DoesPadExist(padID string) (*bool, error) {
if err != nil {
return nil, err
}
defer query.Close()

for query.Next() {
trueVal := true
return &trueVal, nil
}

defer query.Close()
falseVal := false
return &falseVal, nil
}
Expand Down Expand Up @@ -870,6 +870,7 @@ func (d PostgresDB) GetPadMetaData(padId string, revNum int) (*db.PadMetaData, e
if err != nil {
return nil, err
}
defer query.Close()

var padMetaData db.PadMetaData
for query.Next() {
Expand All @@ -884,7 +885,6 @@ func (d PostgresDB) GetPadMetaData(padId string, revNum int) (*db.PadMetaData, e

return &padMetaData, nil
}
defer query.Close()

return nil, errors.New(PadRevisionNotFoundError)
}
Expand All @@ -908,6 +908,11 @@ func NewPostgresDB(options PostgresOptions) (*PostgresDB, error) {
if err != nil {
return nil, err
}

// Set connection pool limits to avoid "too many clients" error
sqlDb.SetMaxOpenConns(25)
sqlDb.SetMaxIdleConns(5)

_, err = sqlDb.Exec("CREATE TABLE IF NOT EXISTS pad (id TEXT PRIMARY KEY, data TEXT)")

_, err = sqlDb.Exec("CREATE TABLE IF NOT EXISTS globalAuthor(id TEXT PRIMARY KEY, colorId TEXT, name TEXT, timestamp BIGINT)")
Expand Down
37 changes: 22 additions & 15 deletions lib/io/exportDocx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"archive/zip"
"bytes"
"fmt"
"regexp"
"strconv"
"strings"

"github.com/ether/etherpad-go/lib/apool"
Expand Down Expand Up @@ -304,24 +306,29 @@ func (e *ExportDocx) parseLineSegments(text string, aline string, padPool *apool
// parseListType extracts the list type and level from a list attribute value
// e.g., "bullet1" -> ("bullet", 1), "number2" -> ("number", 2)
func parseListType(listAttr string) (string, int) {
if strings.HasPrefix(listAttr, "bullet") {
level := 1
if len(listAttr) > 6 {
if l, err := fmt.Sscanf(listAttr[6:], "%d", &level); err != nil || l != 1 {
level = 1
}
}
// Use regex to match any list type like bullet1, number1, indent1, etc.
re := regexp.MustCompile(`^([a-z]+)([0-9]+)`)
m := re.FindStringSubmatch(listAttr)
if m == nil {
return "", 0
}

level, _ := strconv.Atoi(m[2])
tag := m[1]

// Map Etherpad list types to DOCX list types
switch tag {
case "bullet":
return "bullet", level
} else if strings.HasPrefix(listAttr, "number") {
level := 1
if len(listAttr) > 6 {
if l, err := fmt.Sscanf(listAttr[6:], "%d", &level); err != nil || l != 1 {
level = 1
}
}
case "number":
return "number", level
case "indent":
// indent is treated as bullet list without bullet char
return "bullet", level
default:
// Unknown list type, treat as bullet
return "bullet", level
}
return "", 0
}

// DOCX XML Templates
Expand Down
10 changes: 10 additions & 0 deletions lib/io/exportEtherpad.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type ExportEtherpad struct {
exportTxt *ExportTxt
exportPDF *ExportPDF
exportDocx *ExportDocx
exportOdt *ExportOdt
logger *zap.SugaredLogger
}

Expand All @@ -43,6 +44,7 @@ func NewExportEtherpad(hooks *hooks.Hook, padManager *pad.Manager, db db.DataSto
authorManager: authorMgr,
},
exportDocx: NewExportDocx(padManager, authorMgr),
exportOdt: NewExportOdt(padManager, authorMgr),
logger: logger,
}
}
Expand Down Expand Up @@ -208,6 +210,14 @@ func (e *ExportEtherpad) DoExport(ctx *fiber.Ctx, id string, readOnlyId *string,
return ctx.Status(500).SendString(err.Error())
}
return ctx.Send(docxBytes)
case "odt":
ctx.Set("Content-Type", "application/vnd.oasis.opendocument.text")
odtBytes, err := e.exportOdt.GetPadOdtDocument(id, optRevNum)
if err != nil {
e.logger.Warnf("Failed to get odt document for id: %s with cause %s", id, err.Error())
return ctx.Status(500).SendString(err.Error())
}
return ctx.Send(odtBytes)
default:
return ctx.Status(400).SendString("Not Implemented")
}
Expand Down
Loading
Loading