onlyoffice

package
v0.52.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 39 Imported by: 0

Documentation

Overview

Package onlyoffice integrates a self-hosted OnlyOffice Document Server with filex storage backends.

Three pieces cooperate:

  • Config: builds a JWT-signed editor descriptor for the embed iframe. Includes a signed fetch URL the document server uses to pull source bytes from filex.
  • Fetch: serves source bytes back to the document server (HMAC-signed URL). Public — no session required, but the URL is unguessable and short-lived.
  • Callback: receives save events from the document server, validates the JWT it sends, downloads the saved revision, and writes back to storage.

All signing uses HS256 (HMAC-SHA256) with the JWTSecret loaded from config (FILEX_ONLYOFFICE_JWT). That same secret is what the document server has in its `local.json` -> `services.CoAuthoring.token.enable` stanza.

Index

Constants

View Source
const (
	// AuditActionSavedBeside: an edit the document server saved in another
	// format was written beside the file, which was left as it was.
	AuditActionSavedBeside = "file.office_saved_beside"
	// AuditActionSaveRefused: the document server's save was not written.
	AuditActionSaveRefused = "file.office_save_refused"
)

Audit actions (web/tests/lib/auditLabel.test.ts holds their labels).

View Source
const (
	DSUnknown  = -1  // unknown error, a storage or queue failure
	DSTimeout  = -2  // the conversion took too long, or the task was dead-lettered
	DSConvert  = -3  // the converter could not read or convert the file
	DSDownload = -4  // the document server could not download the source
	DSPassword = -5  // the file is protected by a password (or DRM)
	DSResultDB = -6  // the conversion result database could not be reached
	DSParams   = -7  // the request's input is wrong for this file
	DSToken    = -8  // the token is missing or wrong
	DSDetect   = -9  // the output format could not be determined
	DSLimit    = -10 // a size limit: the download, or the file's content

)

Conversion error codes the document server answers (`error`). The names are filex's; the numbers are the document server's (Common/sources/utils.js, mapAscServerErrorToOldError).

View Source
const (
	FetchBadLink            = "bad_link"
	FetchSignatureExpired   = "signature_expired"
	FetchSignatureBad       = "signature_bad"
	FetchNotFound           = "not_found"
	FetchStorageUnavailable = "storage_unavailable"
	FetchBodyUnavailable    = "body_unavailable"
	FetchObjectMissing      = "object_missing"
	FetchReadFailed         = "read_failed"
)

Reason codes for a refused fetch (FetchOutcome.Code). The editor words them in the reader's language; Reason is the English the log line carries.

View Source
const (
	// VerdictServed: the document server downloaded the document and filex
	// served it. A "Download failed" after that is the browser's leg: the
	// converted copy could not be loaded from the document server.
	VerdictServed = "served"
	// VerdictNotRequested: the document server has not asked filex for the
	// document since filex last opened it (or ever). If the document was
	// opened before, the document server may be using its own converted copy.
	VerdictNotRequested = "not_requested"
	// VerdictRefused: the document server asked and filex refused; the
	// outcome's Code and Reason say why.
	VerdictRefused = "refused"
)

Verdicts (Diagnosis.Verdict).

View Source
const (
	PurposeThumb   = "thumb"
	PurposeConvert = "convert"
)

The purposes a fetch address may name.

View Source
const (
	// AdviceCheckJWT: the document server answered -4 and filex cannot tell
	// whether it enforces JWT. Check that first: by default the document
	// server fetches the address in a signed request without its
	// private-address filter (see downloadAdvice for where that is set), so
	// with JWT on a container address is fine and the filter is not the
	// cause. The filter matters with JWT off, or when that default was turned
	// off.
	AdviceCheckJWT = "check_jwt"
	// AdviceJWTOff: -4, and the document server took an unsigned request. With
	// JWT off it applies its private-address filter to every download (a
	// container network is private), and its save callbacks arrive unsigned.
	// Turning JWT on with filex's secret fixes both.
	AdviceJWTOff = "jwt_off"
	// AdviceRoute: -4 from a document server that enforces JWT. By default
	// the filter does not apply to this signed request, so it could not reach
	// filex at that address (name, network, proxy).
	AdviceRoute = "route"
	// AdviceFilexRefused: the request reached filex and filex refused it.
	// Detail names the reason.
	AdviceFilexRefused = "filex_refused"
)

Advice codes for a failed download (ReverseResult.Advice).

View Source
const (
	StatusBeingEdited    = 1
	StatusReadyForSaving = 2
	StatusSavingError    = 3
	StatusClosedNoChange = 4
	StatusForceSave      = 6
	StatusForceSaveError = 7
)

Status codes per OnlyOffice callback spec.

View Source
const CSVSniffBytes = 64 << 10

CSVSniffBytes is how much of a CSV is read to learn how it is written.

View Source
const FetchEncrypted = "encrypted"

FetchEncrypted is the reason code of a purpose fetch refused because the file is end-to-end encrypted.

View Source
const FetchPath = "/api/files/onlyoffice/fetch"

FetchPath is the endpoint the document server downloads a document from. The reverse-path probe is sent to it too.

View Source
const ProbeNodeID int64 = 0

ProbeNodeID is the node id a probe URL carries. No document has it: node ids start at 1, so the fetch handler can tell a probe from a document by it.

View Source
const PurposeFetchTTL = 10 * time.Minute

PurposeFetchTTL is how long a purpose's fetch address is good for.

View Source
const ScopeThisProcess = "this_process"

ScopeThisProcess is the only Diagnosis.Scope there is: what this filex process saw.

View Source
const ThumbSize = 320

ThumbSize is the box a thumbnail's page is drawn into, in pixels: the pipeline's own JPEG is at most this large on either side, and asking for more would only be scaled away.

Variables

View Source
var (
	ErrSignatureExpired = errors.New("onlyoffice: signature expired")
	ErrBadSignature     = errors.New("onlyoffice: bad signature")
)

The two ways a fetch signature is refused. Callers tell them apart with errors.Is: an expired link and a wrong secret want different advice.

View Source
var DefaultCSVDialect = CSVDialect{Comma: ',', UTF8: true}

DefaultCSVDialect is a CSV with nothing to say about itself: an empty file, or one filex could not read. Comma-separated UTF-8, no byte order mark, "\n" line ends.

View Source
var ErrForeignOrigin = errors.New("the result is not on the document server's address")

ErrForeignOrigin is a result address outside the document server's origin.

View Source
var ErrNotConfigured = errors.New("onlyoffice: not configured")

ErrNotConfigured: OnlyOffice is not configured in filex right now (no document server address, or no secret).

View Source
var ErrOfferGone = errors.New("onlyoffice: no such offered file")

ErrOfferGone: the address names no file on offer (never offered, withdrawn, or expired).

View Source
var ErrResultTooLarge = errors.New("the result is larger than allowed")

ErrResultTooLarge is a result over FetchResult's maxBytes.

View Source
var ErrUnknownPurpose = errors.New("onlyoffice: unknown fetch purpose")

ErrUnknownPurpose: a fetch address names a purpose filex does not hand out.

Functions

func ConvertKey added in v0.50.0

func ConvertKey(parts ...string) string

ConvertKey is a conversion key made of parts: the same parts, the same key. Callers name everything the result depends on - which filex and which file (the fetch address's base, the storage, the node), the content (its fingerprint), the parameters (a version string the caller bumps when it changes what it asks for) and the attempt - because the document server answers a key it has seen with what it made then (see the package comment).

The key is "fx" and 40 hex digits: the document server takes 128 of [0-9A-Za-z.=_-].

func DocumentType

func DocumentType(ext string) string

DocumentType returns "word", "cell", "slide", or "" for an extension.

Matches the official OnlyOffice mapping. If the extension is unknown we return "" so callers can 415.

func RewriteCSV added in v0.51.0

func RewriteCSV(saved []byte, d CSVDialect) []byte

RewriteCSV turns the CSV the document server saved (comma-separated, a UTF-8 byte order mark, "\n" line ends) back into the file's own way of writing: its delimiter, its byte order mark or none, its line ends. The values are not touched: they stay ONLYOFFICE's, `7` for a cell that held `007`. KeepCSV is what keeps the file's own text, and this is what is written when it cannot. A field is quoted when the delimiter, a quote or a line end is in it.

func ValidPurpose added in v0.50.0

func ValidPurpose(p string) bool

ValidPurpose reports whether p is a purpose a fetch address may name.

Types

type CSVDialect added in v0.51.0

type CSVDialect struct {
	// Comma is the delimiter: ',', ';', '\t' or '|'.
	Comma byte
	// BOM: the file starts with a UTF-8 byte order mark.
	BOM bool
	// CRLF: its lines end in "\r\n" (else "\n").
	CRLF bool
	// UTF8: its bytes are UTF-8 (ASCII included). False for UTF-16 and for a
	// legacy code page.
	UTF8 bool
}

CSVDialect is how a CSV file is written.

func SniffCSV added in v0.51.0

func SniffCSV(head []byte) CSVDialect

SniffCSV reads how a CSV is written from its first bytes (CSVSniffBytes of them is plenty; fewer is fine). The delimiter is the candidate that splits the first lines (outside quotes) into the same number of fields, the most of them; with none consistent, the most frequent; with none at all, a comma.

func (CSVDialect) KeepsBOM added in v0.51.0

func (d CSVDialect) KeepsBOM() bool

KeepsBOM reports whether the saved file starts with a byte order mark: when the file had one, and when it was not UTF-8 (the save is UTF-8 now, and the mark is what tells a reader so).

func (CSVDialect) OpenOptions added in v0.51.0

func (d CSVDialect) OpenOptions() map[string]any

OpenOptions is the editor config's `document.options` that opens the CSV without ONLYOFFICE's "Choose CSV options" dialog: UTF-8 and its delimiter. Nil for a file that is not UTF-8: the dialog asks which encoding it is.

type CSVKept added in v0.52.0

type CSVKept struct {
	// Applied: the cells were kept. False: the bytes are RewriteCSV's.
	Applied bool
	// Why they were not: "empty" (the file on storage has no record),
	// "not_utf8", "too_large", "too_many_records", "too_many_fields" (in one
	// record), "check_failed" (the result did not read back as the save),
	// "panic".
	Why string
	// Panic, when Why is "panic": what panicked and where, for the log. A
	// runtime panic names indexes, never a cell's text.
	Panic string
	// Records written.
	Records int
	// Unchanged records, written from the file's own bytes.
	Unchanged int
	// Restored cells: in a record somebody changed, the cells whose own text
	// was put back over ONLYOFFICE's way of writing it.
	Restored int
	// New records: saved ones with no record of the file behind them.
	New int
	// Deleted records: the file's, with no saved record.
	Deleted int
}

CSVKept says what KeepCSV did, for the log and the tests.

func KeepCSV added in v0.52.0

func KeepCSV(original, saved []byte, d CSVDialect) ([]byte, CSVKept)

KeepCSV turns the CSV the document server saved into the bytes to write, with the text of every cell nobody changed as it is in original, the file on storage: a record in which nothing changed byte for byte, the unchanged cells of a changed one, new records in the file's dialect. d is how the original is written (SniffCSV). When the cells cannot be kept the bytes are RewriteCSV(saved, d) and CSVKept says why.

type CallbackPayload

type CallbackPayload struct {
	Key    string `json:"key"`
	Status int    `json:"status"`
	URL    string `json:"url"`
	Token  string `json:"token,omitempty"`
	// FileType is the type of the document at URL ("csv", "xlsx", ...). The
	// server saves in the document's own type by default
	// (`assemblyFormatAsOrigin`), in OOXML when that is off (filex 0.51,
	// callback_csv.go).
	FileType string `json:"filetype,omitempty"`
	// Users are the editors of the session: the user ids the editor config
	// named, filex account ids.
	Users []string `json:"users,omitempty"`
}

CallbackPayload is the body the document server posts on save / status transitions. See https://api.onlyoffice.com/editors/callback for the full schema; we use the fields filex actually needs.

type ConfigOption added in v0.51.0

type ConfigOption func(*configExtras)

ConfigOption adds to an editor config what only the caller knows.

func WithHead added in v0.51.0

func WithHead(head []byte) ConfigOption

WithHead hands over the first bytes of the document (CSVSniffBytes is plenty): for a CSV they say its delimiter and encoding, which the config passes on so ONLYOFFICE opens it without asking (csv.go).

type ConvertError added in v0.50.0

type ConvertError struct {
	// Code is the document server's error number (-1 to -10), 0 when the
	// failure was not its answer (the network, an HTTP error, a timeout).
	Code int
	// Class says what it means (ClassOf, or transient for everything that is
	// not the document server's answer).
	Class ErrorClass
	// HTTPStatus is the status of an answer that was not a conversion answer.
	HTTPStatus int
	// What is the short name a record keeps: "ds-3", "http-502", "net",
	// "timeout", "answer", "origin", "result". Never a URL, never a secret.
	What string
	Err  error
}

ConvertError is why a conversion did not give a result.

func AsConvertError added in v0.50.0

func AsConvertError(err error) (*ConvertError, bool)

AsConvertError returns err as a *ConvertError, and false for any other error.

func (*ConvertError) Error added in v0.50.0

func (e *ConvertError) Error() string

func (*ConvertError) Unwrap added in v0.50.0

func (e *ConvertError) Unwrap() error

type ConvertRequest added in v0.50.0

type ConvertRequest struct {
	// FetchURL is where the document server downloads the source: filex's
	// signed fetch address for a purpose (PurposeFetchURL).
	FetchURL string
	// FileType is the source's type: its extension, lower case, no dot.
	FileType string
	// OutputType is what to make: "png" for a thumbnail, "pdf", "docx", ...
	OutputType string
	// Title is the file's name, for the document server's log and the
	// result's name.
	Title string
	// Key is the conversion's key (ConvertKey). Required.
	Key string
	// Thumbnail and SpreadsheetLayout are optional.
	Thumbnail         *Thumbnail
	SpreadsheetLayout *SpreadsheetLayout
	// CodePage and Delimiter are the conversion API's CSV and text knobs
	// (`codePage`, `delimiter`); zero leaves them out.
	CodePage  int
	Delimiter int
}

ConvertRequest is one file to convert.

type ConvertResult added in v0.50.0

type ConvertResult struct {
	FileURL  string
	FileType string
}

ConvertResult is a finished conversion: where its result is, and its type.

type Converter added in v0.50.0

type Converter struct {
	// DocumentServerURL is the document server's base address, as filex is
	// configured with it. Results are only fetched from its origin.
	DocumentServerURL string
	// Secret signs every request; empty sends them unsigned (only the
	// reverse-path probe's JWT question does).
	Secret string
	// HTTP is the client requests go through (nil: a default one without a
	// timeout of its own; the caller's context bounds every request).
	HTTP *http.Client
	// PollFirst and PollMax are the wait before the first poll and the
	// longest wait between two (zero: 200 ms and 1 s).
	PollFirst, PollMax time.Duration
}

Converter talks to one document server.

func (*Converter) Convert added in v0.50.0

func (c *Converter) Convert(ctx context.Context, r ConvertRequest) (*ConvertResult, error)

Convert asks for one conversion and polls until it ends: the result, or a *ConvertError. The caller's context bounds it (a per-file deadline belongs there): when it ends first the error is a transient "timeout".

func (*Converter) FetchResult added in v0.50.0

func (c *Converter) FetchResult(ctx context.Context, res *ConvertResult, maxBytes int64) ([]byte, error)

FetchResult downloads a finished conversion's result, at most maxBytes of it, and only from the document server's own origin (see the package comment). A result over maxBytes is an error, not a truncated file.

type Diagnosis added in v0.50.0

type Diagnosis struct {
	Verdict string `json:"verdict"`
	// OpenedAt is when filex last handed out an editor configuration for the
	// document.
	OpenedAt *time.Time `json:"opened_at,omitempty"`
	// Fetch is the last answer filex gave the document server for it.
	Fetch *FetchOutcome `json:"fetch,omitempty"`
	Scope string        `json:"scope"`
}

Diagnosis is the answer to "the editor said Download failed: what did filex see?".

type EditorConfig

type EditorConfig struct {
	DocumentServerURL string         `json:"documentServerUrl"`
	Config            map[string]any `json:"config"`
}

EditorConfig is the descriptor we send to the embed iframe.

type ErrorClass added in v0.50.0

type ErrorClass string

ErrorClass is what a conversion failure means for whoever asked: whether asking again can help, and what to tell the person looking at the file.

const (
	// ClassTransient: asking again later may work - the network, the
	// document server's own trouble (-1, -2, -6), a token it refused (-8,
	// a secret being changed), a download that did not reach filex (-4), a
	// timeout, an answer filex could not read, a result it could not fetch.
	ClassTransient ErrorClass = "transient"
	// ClassCorrupt: the file cannot be converted (-3, -7, -9). The same
	// bytes will fail again.
	ClassCorrupt ErrorClass = "corrupt"
	// ClassPassword: the file is protected by a password (-5).
	ClassPassword ErrorClass = "password"
	// ClassTooLarge: over the document server's own size limits (-10).
	ClassTooLarge ErrorClass = "too_large"
)
const ClassEncrypted ErrorClass = "encrypted"

ClassEncrypted: filex refused to send the document (it is end-to-end encrypted), so the document server answered -4.

func ClassOf added in v0.50.0

func ClassOf(code int) ErrorClass

ClassOf classifies a document server error code.

type FetchOutcome added in v0.50.0

type FetchOutcome struct {
	At     time.Time `json:"at"`
	Status int       `json:"status"`
	Code   string    `json:"reason_code,omitempty"`
	Reason string    `json:"reason,omitempty"`
}

FetchOutcome is what filex answered one request of the document server's.

type LayoutMargin added in v0.50.0

type LayoutMargin struct {
	Left   string `json:"left"`
	Right  string `json:"right"`
	Top    string `json:"top"`
	Bottom string `json:"bottom"`
}

LayoutMargin is a page's margins, with their unit ("2mm").

type LayoutSize added in v0.50.0

type LayoutSize struct {
	Width  string `json:"width"`
	Height string `json:"height"`
}

LayoutSize is a page size, with its unit ("120mm").

type PurposeOutcome added in v0.50.0

type PurposeOutcome struct {
	At     time.Time
	Status int
	Code   string
}

PurposeOutcome is what filex answered one purpose fetch.

type ReverseResult

type ReverseResult struct {
	// Checked is false when the question could not be put at all — nothing
	// configured, or the document server did not answer. A false here must
	// never be rendered as a failure of the route.
	Checked bool `json:"checked"`
	// OK is true only when the probe request actually ARRIVED at filex and
	// filex served it, the way it serves a document.
	OK bool `json:"ok"`
	// URL is the address the document server was asked to fetch, so an
	// operator reading a red result can try it themselves.
	URL string `json:"url,omitempty"`
	// Code is the document server's own error number when it returned one.
	// -4 is "error while downloading the document file" — the shape of a
	// broken reverse path. 0 means it did not report an error.
	Code int `json:"code,omitempty"`
	// Detail is the sentence to show the operator.
	Detail string `json:"detail,omitempty"`
	// Advice says what to look at first when the document server could not
	// download the probe (one of the Advice* codes). Empty when there is
	// nothing to advise. A client that wants its own wording keys off this,
	// never off Detail.
	Advice string `json:"advice,omitempty"`
	// JWTEnforced answers the second question: did the document server refuse
	// a request that carried no token? true: it enforces JWT. false: it took
	// an unsigned request, so it refuses filex's editor token (it checks it
	// against its own secret) and sends its save callbacks unsigned, which
	// filex refuses. Absent: it could not be told.
	JWTEnforced *bool `json:"jwt_enforced,omitempty"`
}

ReverseResult is one answer to "can the document server reach filex?".

type Service

type Service struct {
	Store           db.Store
	StorageResolver func(int64) (storage.Driver, error)

	// DocumentServerURL / JWTSecret are the BOOT-TIME values (env/YAML). They
	// are the fallback only: when Live is wired the running configuration is
	// read from the `external_services` row on every call, so an operator who
	// configures OnlyOffice in the admin UI does not have to restart filex.
	// See internal/external and issue #17.
	DocumentServerURL string // e.g. https://docs.example.com
	JWTSecret         string // shared secret with the doc server
	// Live, when non-nil, returns the current url + secret. Nil means "use the
	// fields", which is what the unit tests and any no-DB caller want.
	Live      func(ctx context.Context) (url, secret string)
	PublicURL string // filex public base URL — used to build callbacks
	// LiveCallbackURL, when non-nil, returns the address the DOCUMENT SERVER
	// should use to reach filex. Empty result means "the public URL".
	//
	// ⚠ These are two different addresses for two different readers. PublicURL
	// is what a person's browser uses and what every share link is built from;
	// this one is only ever read by the document server's container. They are
	// usually the same string, and on podman or a private network they cannot
	// be — which is why a document opened and its save never came back with
	// nothing in filex's log to show for it (issue #17).
	LiveCallbackURL func(ctx context.Context) string
	FetchTTL        time.Duration

	// Body resolves where a document's bytes are: the driver, or filex's
	// staging area while a staged upload is still transferring. It is the
	// resolver the fetch endpoint serves the document server from, so the
	// callback compares a saved CSV with the bytes the editor was given
	// (callback_csv.go csvOriginal). Nil-safe: it then answers the driver.
	Body *filebody.Resolver

	// Sync is the shared post-write gate every other write surface in filex
	// goes through: it upserts the node row, re-indexes the document,
	// dispatches a thumbnail, tells open explorers, emits the canonical
	// `file.updated` webhook event and schedules the antivirus scan.
	//
	// ⚠ Optional, and its absence degrades gracefully rather than silently:
	// an unwired Service falls back to a Syncer with no search index (see
	// syncer), so a save still announces itself and is still scanned — only
	// the re-index is skipped. Wire it with AttachSync at boot.
	Sync *protocolsync.Syncer
	// contains filtered or unexported fields
}

Service builds editor configs and validates document-server callbacks.

func New

func New(store db.Store, resolver func(int64) (storage.Driver, error), docURL, jwtSecret, publicURL string, fetchTTL time.Duration) *Service

New constructs a Service. fetchTTL defaults to 1 hour when zero.

func (*Service) AttachBody added in v0.52.0

func (s *Service) AttachBody(b *filebody.Resolver)

AttachBody wires the byte-source resolver, the one the fetch endpoint reads a document through.

func (*Service) AttachSync

func (s *Service) AttachSync(sy *protocolsync.Syncer)

AttachSync wires the post-write gate. ⚠ Without it an edited document keeps its PRE-EDIT text in content search, because nothing else ever revisits a file whose path did not change.

func (*Service) BuildConfigForNode

func (s *Service) BuildConfigForNode(ctx context.Context, node *model.Node, user *model.User, lang, mode string, opts ...ConfigOption) (*EditorConfig, error)

BuildConfigForNode resolves the node, presigns the fetch URL, and signs the JSON descriptor with HS256. `mode` selects "edit" or "view"; any value other than "edit" is treated as read-only and toggles the permissions block so OnlyOffice renders the document with toolbars disabled.

func (*Service) CheckReversePath added in v0.50.0

func (s *Service) CheckReversePath(ctx context.Context, t *Target) ReverseResult

CheckReversePath asks the document server to download a one-shot URL from filex and reports whether that request arrived and was served. t nil means the configuration in force.

⚠ The verdict is the ARRIVAL. The conversion result is a hint for the message, never the answer: a document server that downloaded our probe and then failed to convert it has still proved the only thing being asked.

func (*Service) Converter added in v0.50.0

func (s *Service) Converter(ctx context.Context) (*Converter, error)

Converter is a conversion client for the document server in force, or ErrNotConfigured.

func (*Service) Diagnose added in v0.50.0

func (s *Service) Diagnose(nodeID int64) Diagnosis

Diagnose says what this process saw of the document server's requests for the document.

func (*Service) DrawThumbnail added in v0.50.0

func (s *Service) DrawThumbnail(ctx context.Context, r ThumbRequest) ([]byte, error)

DrawThumbnail asks the document server for a PNG of the document's first page, ThumbSize on its longer side, and downloads it. A failure is a *ConvertError (ErrNotConfigured when OnlyOffice is not configured): a -4 whose download filex itself refused because the file is end-to-end encrypted comes back as ClassEncrypted.

func (*Service) Enabled

func (s *Service) Enabled() bool

Enabled reports whether the service has the minimum config to run, as of this instant — not as of the last restart.

func (*Service) EnabledCtx

func (s *Service) EnabledCtx(ctx context.Context) bool

EnabledCtx is Enabled with a caller-supplied context, so the DB read that backs it inherits the request's deadline and cancellation.

func (*Service) HandleCallback

func (s *Service) HandleCallback(r *http.Request, nodeID int64) (map[string]any, error)

HandleCallback validates the JWT, downloads the saved version, and writes it back to storage.

Returns the OnlyOffice expected JSON envelope.

func (*Service) LastPurposeFetch added in v0.50.0

func (s *Service) LastPurposeFetch(nodeID int64, purpose string) (PurposeOutcome, bool)

LastPurposeFetch is what filex last answered the document server's fetch of node for purpose (false: it never asked, as far as this process knows).

func (*Service) LiveTarget added in v0.50.0

func (s *Service) LiveTarget(ctx context.Context) Target

LiveTarget is the configuration in force right now.

func (*Service) NoteFetch added in v0.50.0

func (s *Service) NoteFetch(nodeID int64, status int, code, reason string, signed bool)

NoteFetch records what the fetch endpoint answered for the document. signed says the request's signature checked out: only such a request may add a document to the log; any other only updates a document already in it.

func (*Service) NotePurposeFetch added in v0.50.0

func (s *Service) NotePurposeFetch(nodeID int64, purpose string, status int, code string)

NotePurposeFetch records what the fetch endpoint answered a SIGNED purpose fetch (an unsigned one is refused before it is anybody's). The oldest entry goes when the record is full.

func (*Service) OfferFile added in v0.50.0

func (s *Service) OfferFile(ctx context.Context, path, name string) (string, func(), error)

OfferFile puts the file at path on offer to the document server and answers the address it downloads it from, and the function that withdraws it (call it when the conversion ends, whatever the outcome). name is what the download is called. ErrNotConfigured when OnlyOffice is not configured.

func (*Service) OpenOffered added in v0.50.0

func (s *Service) OpenOffered(ctx context.Context, token string, exp int64, purpose, sig string) (*os.File, string, error)

OpenOffered checks an offered file's address and opens the file: the file, the name it is offered under, or ErrUnknownPurpose, ErrSignatureExpired, ErrBadSignature or ErrOfferGone.

func (*Service) PurposeFetchURL added in v0.50.0

func (s *Service) PurposeFetchURL(ctx context.Context, nodeID int64, purpose string) (string, error)

PurposeFetchURL is the address the document server downloads node from for a purpose: the fetch endpoint on the address the document server reaches filex at (callbackBase), signed with the secret in force and the purpose.

func (*Service) ServeFetchProbe added in v0.50.0

func (s *Service) ServeFetchProbe(ctx context.Context, token string, exp int64, sig string) (int, string)

ServeFetchProbe answers a probe that arrived at the fetch endpoint (a request for node ProbeNodeID carrying a probe token `t`). It returns the HTTP status to answer with and, on 200, the body.

It asks what a document's fetch asks, in the same order: is OnlyOffice configured in filex right now, and is the signature good (the same HMAC, checked by VerifyFetchSignatureCtx). A probe made from the admin page's unsaved values is verified against those values instead, because they are what is being tested. An unknown or expired token is a plain 404 and leaves no trace: a stranger who guesses at it learns nothing.

func (*Service) SignedFetchURL

func (s *Service) SignedFetchURL(nodeID, exp int64) string

SignedFetchURL returns an HMAC-signed URL the document server can use to pull document bytes from filex without authenticating.

The URL embeds node id + expiry + sig=base64-url(HMAC-SHA256(secret, "n=<id>&exp=<exp>")).

func (*Service) ThumbKey added in v0.50.0

func (s *Service) ThumbKey(ctx context.Context, r ThumbRequest) string

ThumbKey is the conversion key of a thumbnail (ConvertKey): which filex (the address the document server reaches it at), which file, which content, which parameters and which attempt.

func (*Service) VerifyFetchSignature

func (s *Service) VerifyFetchSignature(nodeID, exp int64, sig string) error

VerifyFetchSignature validates a query against the fetch HMAC.

func (*Service) VerifyFetchSignatureCtx

func (s *Service) VerifyFetchSignatureCtx(ctx context.Context, nodeID, exp int64, sig string) error

VerifyFetchSignatureCtx is VerifyFetchSignature with the request context, so the secret is the one in force now.

func (*Service) VerifyPurposeFetchCtx added in v0.50.0

func (s *Service) VerifyPurposeFetchCtx(ctx context.Context, nodeID, exp int64, purpose, sig string) error

VerifyPurposeFetchCtx checks a purpose's fetch address against the secret in force: ErrUnknownPurpose, ErrSignatureExpired or ErrBadSignature.

func (*Service) VerifyReversePath

func (s *Service) VerifyReversePath(ctx context.Context) ReverseResult

VerifyReversePath runs the reverse-path check against the configuration in force.

type SpreadsheetLayout added in v0.50.0

type SpreadsheetLayout struct {
	IgnorePrintArea bool          `json:"ignorePrintArea"`
	Orientation     string        `json:"orientation,omitempty"`
	FitToWidth      int           `json:"fitToWidth"`
	FitToHeight     int           `json:"fitToHeight"`
	GridLines       bool          `json:"gridLines"`
	Headings        bool          `json:"headings"`
	PageSize        *LayoutSize   `json:"pageSize,omitempty"`
	Margins         *LayoutMargin `json:"margins,omitempty"`
}

SpreadsheetLayout lays a spreadsheet out on a page before it is converted to a page format (a PDF, a picture). Without it a sheet is cut where the default A4 page ends and a thumbnail shows a corner of the first columns.

type Target added in v0.50.0

type Target struct {
	DocumentServerURL string
	Secret            string
	// CallbackURL is the address the document server is sent to. Empty means
	// filex's public URL, as for a document.
	CallbackURL string
	// Draft marks values that are not the ones in force (the admin page's
	// unsaved form). The probe is verified against them rather than against
	// the saved configuration, which would refuse a candidate secret.
	Draft bool
}

Target is the configuration a reverse-path check runs against.

type ThumbRequest added in v0.50.0

type ThumbRequest struct {
	NodeID    int64
	StorageID int64
	// Name is the file's name; its extension is the type the document server
	// is told.
	Name string
	// ContentSig is the content's fingerprint (what the thumbnail row
	// records): a new version of the file is a new conversion key.
	ContentSig string
	// Attempt counts the tries at this content, from 1: a retry is a new key,
	// so a failure the document server cached is not answered again.
	Attempt int
	// MaxBytes is the largest result accepted (0: 32 MB).
	MaxBytes int64
}

ThumbRequest is one document to draw a thumbnail of.

type Thumbnail added in v0.50.0

type Thumbnail struct {
	Aspect int  `json:"aspect"`
	First  bool `json:"first"`
	Width  int  `json:"width,omitempty"`
	Height int  `json:"height,omitempty"`
}

Thumbnail asks for a picture of the first page instead of a document (outputtype png, jpg, bmp or gif). Aspect 1 keeps the page's proportions inside Width x Height; First is the first page only.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL