2015-04-13 04:09:02 -05:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2015-03-04 17:14:04 -06:00
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*/
2015-04-27 07:51:33 -05:00
# include <sys/stat.h>
# include <sys/types.h>
2015-04-08 09:22:42 -05:00
# include <ftw.h>
2015-04-27 07:51:33 -05:00
# include <utime.h>
2015-04-08 09:22:42 -05:00
2015-03-17 18:56:15 -05:00
# include <cassert>
2015-05-07 08:29:36 -05:00
# include <condition_variable>
2015-03-12 09:18:35 -05:00
# include <cstring>
2015-03-04 17:14:04 -06:00
# include <fstream>
# include <iostream>
2015-04-30 07:58:13 -05:00
# include <iterator>
2015-04-08 09:22:42 -05:00
# include <map>
2015-03-12 09:18:35 -05:00
# include <memory>
2015-05-07 08:29:36 -05:00
# include <mutex>
2015-04-08 09:22:42 -05:00
# include <set>
2015-03-04 17:14:04 -06:00
2015-03-26 09:49:07 -05:00
# define LOK_USE_UNSTABLE_API
# include <LibreOfficeKit/LibreOfficeKit.h>
# include <LibreOfficeKit/LibreOfficeKitEnums.h>
2015-09-09 12:23:49 -05:00
# include <Poco/Dynamic/Var.h>
2015-05-29 00:49:49 -05:00
# include <Poco/Exception.h>
2015-04-08 09:22:42 -05:00
# include <Poco/File.h>
2015-09-09 12:23:49 -05:00
# include <Poco/JSON/Object.h>
# include <Poco/JSON/Parser.h>
2015-04-30 07:58:13 -05:00
# include <Poco/Net/HTTPStreamFactory.h>
2015-04-08 09:22:42 -05:00
# include <Poco/Net/WebSocket.h>
# include <Poco/Path.h>
2015-03-17 18:56:15 -05:00
# include <Poco/Process.h>
# include <Poco/Random.h>
2015-04-30 10:01:21 -05:00
# include <Poco/StreamCopier.h>
2015-03-04 17:14:04 -06:00
# include <Poco/String.h>
# include <Poco/StringTokenizer.h>
2015-05-07 12:15:05 -05:00
# include <Poco/ThreadLocal.h>
2015-03-23 15:13:57 -05:00
# include <Poco/URI.h>
2015-04-30 07:58:13 -05:00
# include <Poco/URIStreamOpener.h>
2015-03-17 18:56:15 -05:00
# include <Poco/Util/Application.h>
2015-07-04 19:46:13 -05:00
# include <Poco/Exception.h>
2015-07-13 09:13:06 -05:00
# include <Poco/Net/NetException.h>
# include <Poco/Net/DialogSocket.h>
# include <Poco/Net/SocketAddress.h>
2015-08-05 19:20:05 -05:00
# include <Poco/FileStream.h>
2015-03-04 17:14:04 -06:00
2015-03-28 06:22:15 -05:00
# include "LOKitHelper.hpp"
2015-03-26 09:49:07 -05:00
# include "LOOLProtocol.hpp"
2015-03-09 03:01:30 -05:00
# include "LOOLSession.hpp"
2015-03-17 18:56:15 -05:00
# include "LOOLWSD.hpp"
2015-03-12 09:18:35 -05:00
# include "TileCache.hpp"
2015-03-17 18:56:15 -05:00
# include "Util.hpp"
2015-03-04 17:14:04 -06:00
2015-03-26 09:49:07 -05:00
using namespace LOOLProtocol ;
2015-09-09 12:23:49 -05:00
using Poco : : Dynamic : : Var ;
2015-04-08 09:22:42 -05:00
using Poco : : File ;
2015-05-29 00:49:49 -05:00
using Poco : : IOException ;
2015-09-09 12:23:49 -05:00
using Poco : : JSON : : Object ;
using Poco : : JSON : : Parser ;
2015-04-30 07:58:13 -05:00
using Poco : : Net : : HTTPStreamFactory ;
2015-03-04 17:14:04 -06:00
using Poco : : Net : : WebSocket ;
2015-04-08 09:22:42 -05:00
using Poco : : Path ;
2015-03-17 18:56:15 -05:00
using Poco : : Process ;
using Poco : : ProcessHandle ;
using Poco : : Random ;
2015-04-30 10:01:21 -05:00
using Poco : : StreamCopier ;
2015-03-04 17:14:04 -06:00
using Poco : : StringTokenizer ;
2015-03-17 18:56:15 -05:00
using Poco : : Thread ;
2015-05-07 12:15:05 -05:00
using Poco : : ThreadLocal ;
2015-03-17 18:56:15 -05:00
using Poco : : UInt64 ;
2015-03-23 15:13:57 -05:00
using Poco : : URI ;
2015-04-30 07:58:13 -05:00
using Poco : : URIStreamOpener ;
2015-03-17 18:56:15 -05:00
using Poco : : Util : : Application ;
2015-07-04 19:46:13 -05:00
using Poco : : Exception ;
2015-07-13 09:13:06 -05:00
using Poco : : Net : : DialogSocket ;
using Poco : : Net : : SocketAddress ;
using Poco : : Net : : WebSocketException ;
2015-03-17 18:56:15 -05:00
2015-04-20 09:43:31 -05:00
const std : : string LOOLSession : : jailDocumentURL = " /user/thedocument " ;
2015-04-08 09:22:42 -05:00
2015-05-28 08:42:38 -05:00
LOOLSession : : LOOLSession ( std : : shared_ptr < WebSocket > ws , Kind kind ) :
2015-04-20 09:43:31 -05:00
_kind ( kind ) ,
2015-05-28 08:42:38 -05:00
_ws ( ws ) ,
2015-04-22 11:48:20 -05:00
_docURL ( " " )
2015-03-04 17:14:04 -06:00
{
2015-05-28 08:42:38 -05:00
std : : cout < < Util : : logPrefix ( ) < < " LOOLSession ctor this= " < < this < < " " < < _kind < < " ws= " < < _ws . get ( ) < < std : : endl ;
2015-07-20 04:54:08 -05:00
if ( kind = = Kind : : ToClient ) {
_kindString = " ToClient " ;
}
else if ( kind = = Kind : : ToMaster ) {
_kindString = " ToMaster " ;
}
else if ( kind = = Kind : : ToPrisoner ) {
_kindString = " ToPrisoner " ;
}
2015-03-04 17:14:04 -06:00
}
2015-03-09 03:01:30 -05:00
LOOLSession : : ~ LOOLSession ( )
2015-03-07 05:23:46 -06:00
{
2015-04-20 09:43:31 -05:00
std : : cout < < Util : : logPrefix ( ) < < " LOOLSession dtor this= " < < this < < " " < < _kind < < std : : endl ;
2015-10-19 03:58:21 -05:00
if ( _ws )
Util : : shutdownWebSocket ( * _ws ) ;
2015-03-07 05:23:46 -06:00
}
2015-04-20 09:43:31 -05:00
void LOOLSession : : sendTextFrame ( const std : : string & text )
{
2015-06-05 08:12:06 -05:00
std : : unique_lock < std : : mutex > lock ( _mutex ) ;
2015-04-20 09:43:31 -05:00
_ws - > sendFrame ( text . data ( ) , text . size ( ) ) ;
}
void LOOLSession : : sendBinaryFrame ( const char * buffer , int length )
{
2015-06-05 08:12:06 -05:00
std : : unique_lock < std : : mutex > lock ( _mutex ) ;
if ( length > 1000 )
{
std : : string nextmessage = " nextmessage: size= " + std : : to_string ( length ) ;
2015-10-19 03:58:21 -05:00
if ( _ws )
_ws - > sendFrame ( nextmessage . data ( ) , nextmessage . size ( ) ) ;
2015-06-05 08:12:06 -05:00
}
2015-10-19 03:58:21 -05:00
if ( _ws )
_ws - > sendFrame ( buffer , length , WebSocket : : FRAME_BINARY ) ;
2015-04-20 09:43:31 -05:00
}
2015-04-13 07:13:38 -05:00
2015-05-07 08:29:36 -05:00
std : : map < Process : : PID , UInt64 > MasterProcessSession : : _childProcesses ;
2015-04-22 13:35:52 -05:00
std : : set < std : : shared_ptr < MasterProcessSession > > MasterProcessSession : : _availableChildSessions ;
2015-05-07 08:29:36 -05:00
std : : mutex MasterProcessSession : : _availableChildSessionMutex ;
std : : condition_variable MasterProcessSession : : _availableChildSessionCV ;
2015-05-29 00:49:49 -05:00
Random MasterProcessSession : : _rng ;
2015-05-07 12:01:40 -05:00
std : : mutex MasterProcessSession : : _rngMutex ;
2015-04-20 09:43:31 -05:00
2015-05-28 08:42:38 -05:00
MasterProcessSession : : MasterProcessSession ( std : : shared_ptr < WebSocket > ws , Kind kind ) :
2015-04-20 09:43:31 -05:00
LOOLSession ( ws , kind ) ,
2015-05-28 10:39:05 -05:00
_childId ( 0 ) ,
2015-08-26 23:18:44 -05:00
_curPart ( 0 ) ,
_loadPart ( - 1 )
2015-04-20 09:43:31 -05:00
{
2015-05-28 08:42:38 -05:00
std : : cout < < Util : : logPrefix ( ) < < " MasterProcessSession ctor this= " < < this < < " ws= " < < _ws . get ( ) < < std : : endl ;
2015-04-20 09:43:31 -05:00
}
MasterProcessSession : : ~ MasterProcessSession ( )
{
2015-04-22 13:35:52 -05:00
std : : cout < < Util : : logPrefix ( ) < < " MasterProcessSession dtor this= " < < this < < " _peer= " < < _peer . lock ( ) . get ( ) < < std : : endl ;
2015-10-19 03:58:21 -05:00
if ( _ws )
Util : : shutdownWebSocket ( * _ws ) ;
2015-04-22 13:35:52 -05:00
auto peer = _peer . lock ( ) ;
if ( _kind = = Kind : : ToClient & & peer )
2015-04-21 07:06:41 -05:00
{
2015-04-22 13:35:52 -05:00
Util : : shutdownWebSocket ( * ( peer - > _ws ) ) ;
2015-04-21 07:06:41 -05:00
}
2015-04-20 09:43:31 -05:00
}
2015-06-08 08:35:52 -05:00
bool MasterProcessSession : : handleInput ( const char * buffer , int length )
2015-03-04 17:14:04 -06:00
{
2015-07-20 04:54:08 -05:00
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + _kindString + " ,Input, " + getAbbreviatedMessage ( buffer , length ) ) ;
2015-03-04 17:14:04 -06:00
2015-04-14 09:50:38 -05:00
std : : string firstLine = getFirstLine ( buffer , length ) ;
StringTokenizer tokens ( firstLine , " " , StringTokenizer : : TOK_IGNORE_EMPTY | StringTokenizer : : TOK_TRIM ) ;
2015-04-20 09:43:31 -05:00
if ( haveSeparateProcess ( ) )
2015-03-17 18:56:15 -05:00
{
2015-04-14 09:50:38 -05:00
// Note that this handles both forwarding requests from the client to the child process, and
2015-04-20 09:43:31 -05:00
// forwarding replies from the child process to the client. Or does it?
2015-03-17 18:56:15 -05:00
2015-05-28 10:39:05 -05:00
// Snoop at some messages and manipulate tile cache information as needed
2015-04-22 13:35:52 -05:00
auto peer = _peer . lock ( ) ;
2015-05-28 10:39:05 -05:00
if ( _kind = = Kind : : ToPrisoner )
{
if ( tokens [ 0 ] = = " curpart: " & &
tokens . count ( ) = = 2 & &
getTokenInteger ( tokens [ 1 ] , " part " , _curPart ) )
{
return true ;
}
2015-10-20 07:03:31 -05:00
if ( tokens . count ( ) = = 2 & & tokens [ 0 ] = = " saveas: " )
{
std : : string url ;
if ( ! getTokenString ( tokens [ 1 ] , " url " , url ) )
return true ;
if ( peer )
2015-10-20 07:44:47 -05:00
{
2015-10-20 07:03:31 -05:00
// Save as completed, inform the other (Kind::ToClient)
// MasterProcessSession about it.
2015-10-20 07:44:47 -05:00
const std : : string filePrefix ( " file:/// " ) ;
if ( url . find ( filePrefix ) = = 0 )
{
// Rewrite file:// URLs, as they are visible to the outside world.
Path path ( MasterProcessSession : : getJailPath ( _childId ) , url . substr ( filePrefix . length ( ) ) ) ;
url = filePrefix + path . toString ( ) . substr ( 1 ) ;
}
2015-10-20 07:03:31 -05:00
peer - > _saveAsQueue . put ( url ) ;
2015-10-20 07:44:47 -05:00
}
2015-10-20 07:03:31 -05:00
return true ;
}
2015-05-28 10:39:05 -05:00
}
2015-04-22 13:35:52 -05:00
if ( _kind = = Kind : : ToPrisoner & & peer & & peer - > _tileCache )
2015-04-14 09:50:38 -05:00
{
if ( tokens [ 0 ] = = " tile: " )
{
2015-04-27 13:24:05 -05:00
int part , width , height , tilePosX , tilePosY , tileWidth , tileHeight ;
2015-07-14 11:46:04 -05:00
if ( tokens . count ( ) < 8 | |
2015-04-27 13:24:05 -05:00
! getTokenInteger ( tokens [ 1 ] , " part " , part ) | |
! getTokenInteger ( tokens [ 2 ] , " width " , width ) | |
! getTokenInteger ( tokens [ 3 ] , " height " , height ) | |
! getTokenInteger ( tokens [ 4 ] , " tileposx " , tilePosX ) | |
! getTokenInteger ( tokens [ 5 ] , " tileposy " , tilePosY ) | |
! getTokenInteger ( tokens [ 6 ] , " tilewidth " , tileWidth ) | |
! getTokenInteger ( tokens [ 7 ] , " tileheight " , tileHeight ) )
2015-04-14 09:50:38 -05:00
assert ( false ) ;
assert ( firstLine . size ( ) < static_cast < std : : string : : size_type > ( length ) ) ;
2015-04-27 13:24:05 -05:00
peer - > _tileCache - > saveTile ( part , width , height , tilePosX , tilePosY , tileWidth , tileHeight , buffer + firstLine . size ( ) + 1 , length - firstLine . size ( ) - 1 ) ;
2015-04-14 09:50:38 -05:00
}
else if ( tokens [ 0 ] = = " status: " )
{
2015-08-18 13:01:05 -05:00
peer - > _tileCache - > saveTextFile ( std : : string ( buffer , length ) , " status.txt " ) ;
}
2015-09-09 12:23:49 -05:00
else if ( tokens [ 0 ] = = " commandvalues: " )
2015-08-18 13:01:05 -05:00
{
2015-11-04 06:38:32 -06:00
std : : string stringMsg ( buffer , length ) ;
2015-09-09 12:23:49 -05:00
std : : string stringJSON = stringMsg . substr ( stringMsg . find_first_of ( " { " ) ) ;
Parser parser ;
Var result = parser . parse ( stringJSON ) ;
Object : : Ptr object = result . extract < Object : : Ptr > ( ) ;
std : : string commandName = object - > get ( " commandName " ) . toString ( ) ;
peer - > _tileCache - > saveTextFile ( std : : string ( buffer , length ) , " cmdValues " + commandName + " .txt " ) ;
2015-04-14 09:50:38 -05:00
}
2015-09-29 05:27:45 -05:00
else if ( tokens [ 0 ] = = " partpagerectangles: " )
{
peer - > _tileCache - > saveTextFile ( std : : string ( buffer , length ) , " partpagerectangles.txt " ) ;
}
2015-09-30 09:17:03 -05:00
else if ( tokens [ 0 ] = = " invalidatecursor: " ) {
peer - > _tileCache - > setEditing ( true ) ;
}
2015-05-28 10:39:05 -05:00
else if ( tokens [ 0 ] = = " invalidatetiles: " )
{
2015-06-24 15:05:49 -05:00
// FIXME temporarily, set the editing on the 1st invalidate, TODO extend
// the protocol so that the client can set the editing or view only.
peer - > _tileCache - > setEditing ( true ) ;
2015-05-28 10:39:05 -05:00
assert ( firstLine . size ( ) = = static_cast < std : : string : : size_type > ( length ) ) ;
2015-07-21 06:53:53 -05:00
peer - > _tileCache - > invalidateTiles ( firstLine ) ;
2015-05-28 10:39:05 -05:00
}
2015-04-14 09:50:38 -05:00
}
2015-03-07 05:23:46 -06:00
2015-04-14 09:50:38 -05:00
forwardToPeer ( buffer , length ) ;
return true ;
}
2015-03-04 17:14:04 -06:00
2015-04-20 09:43:31 -05:00
if ( tokens [ 0 ] = = " child " )
2015-03-17 18:56:15 -05:00
{
2015-04-20 09:43:31 -05:00
if ( _kind ! = Kind : : ToPrisoner )
{
sendTextFrame ( " error: cmd=child kind=invalid " ) ;
return false ;
}
2015-04-22 13:35:52 -05:00
if ( ! _peer . expired ( ) )
2015-03-17 18:56:15 -05:00
{
sendTextFrame ( " error: cmd=child kind=invalid " ) ;
return false ;
}
2015-08-05 19:20:05 -05:00
if ( tokens . count ( ) ! = 3 )
2015-03-17 18:56:15 -05:00
{
sendTextFrame ( " error: cmd=child kind=syntax " ) ;
return false ;
}
2015-07-13 09:13:06 -05:00
2015-03-17 18:56:15 -05:00
UInt64 childId = std : : stoull ( tokens [ 1 ] ) ;
2015-08-05 19:20:05 -05:00
Process : : PID pidChild = std : : stoull ( tokens [ 2 ] ) ;
2015-07-13 09:13:06 -05:00
2015-05-07 08:29:36 -05:00
std : : unique_lock < std : : mutex > lock ( _availableChildSessionMutex ) ;
2015-04-22 13:35:52 -05:00
_availableChildSessions . insert ( shared_from_this ( ) ) ;
2015-05-08 13:24:46 -05:00
std : : cout < < Util : : logPrefix ( ) < < " Inserted " < < this < < " id= " < < childId < < " into _availableChildSessions, size= " < < _availableChildSessions . size ( ) < < std : : endl ;
2015-04-08 09:22:42 -05:00
_childId = childId ;
2015-05-08 13:24:46 -05:00
lock . unlock ( ) ;
2015-05-07 08:29:36 -05:00
_availableChildSessionCV . notify_one ( ) ;
2015-08-05 19:20:05 -05:00
// log first lokit child pid information
if ( LOOLWSD : : doTest )
{
Poco : : FileOutputStream filePID ( LOOLWSD : : LOKIT_PIDLOG ) ;
if ( filePID . good ( ) )
filePID < < pidChild ;
}
2015-03-17 18:56:15 -05:00
}
2015-04-20 09:43:31 -05:00
else if ( _kind = = Kind : : ToPrisoner )
{
// Message from child process to be forwarded to client.
// I think we should never get here
assert ( false ) ;
}
2015-03-17 18:56:15 -05:00
else if ( tokens [ 0 ] = = " load " )
2015-03-04 17:14:04 -06:00
{
2015-03-17 18:56:15 -05:00
if ( _docURL ! = " " )
2015-03-04 17:14:04 -06:00
{
2015-04-13 09:03:55 -05:00
sendTextFrame ( " error: cmd=load kind=docalreadyloaded " ) ;
2015-03-07 05:23:46 -06:00
return false ;
2015-03-04 17:14:04 -06:00
}
2015-03-17 18:56:15 -05:00
return loadDocument ( buffer , length , tokens ) ;
2015-03-04 17:14:04 -06:00
}
2015-06-09 10:04:46 -05:00
else if ( tokens [ 0 ] ! = " canceltiles " & &
2015-11-10 10:31:11 -06:00
tokens [ 0 ] ! = " clientzoom " & &
2015-09-09 12:23:49 -05:00
tokens [ 0 ] ! = " commandvalues " & &
2015-10-09 07:55:49 -05:00
tokens [ 0 ] ! = " downloadas " & &
2015-10-22 10:32:19 -05:00
tokens [ 0 ] ! = " getchildid " & &
2015-06-24 10:08:15 -05:00
tokens [ 0 ] ! = " gettextselection " & &
2015-10-27 04:40:40 -05:00
tokens [ 0 ] ! = " paste " & &
2015-10-22 10:32:19 -05:00
tokens [ 0 ] ! = " insertfile " & &
2015-06-09 10:04:46 -05:00
tokens [ 0 ] ! = " invalidatetiles " & &
2015-05-27 09:14:13 -05:00
tokens [ 0 ] ! = " key " & &
tokens [ 0 ] ! = " mouse " & &
2015-10-09 07:55:49 -05:00
tokens [ 0 ] ! = " partpagerectangles " & &
2015-08-06 10:54:45 -05:00
tokens [ 0 ] ! = " requestloksession " & &
2015-05-27 09:14:13 -05:00
tokens [ 0 ] ! = " resetselection " & &
2015-05-28 10:39:05 -05:00
tokens [ 0 ] ! = " saveas " & &
tokens [ 0 ] ! = " selectgraphic " & &
tokens [ 0 ] ! = " selecttext " & &
2015-07-21 08:56:02 -05:00
tokens [ 0 ] ! = " setclientpart " & &
2015-08-03 11:07:02 -05:00
tokens [ 0 ] ! = " setpage " & &
2015-05-28 10:39:05 -05:00
tokens [ 0 ] ! = " status " & &
tokens [ 0 ] ! = " tile " & &
tokens [ 0 ] ! = " uno " )
2015-05-27 09:14:13 -05:00
{
sendTextFrame ( " error: cmd= " + tokens [ 0 ] + " kind=unknown " ) ;
return false ;
}
2015-03-17 18:56:15 -05:00
else if ( _docURL = = " " )
2015-03-04 17:14:04 -06:00
{
2015-03-13 06:59:51 -05:00
sendTextFrame ( " error: cmd= " + tokens [ 0 ] + " kind=nodocloaded " ) ;
2015-03-07 05:23:46 -06:00
return false ;
2015-03-04 17:14:04 -06:00
}
2015-06-09 10:04:46 -05:00
else if ( tokens [ 0 ] = = " canceltiles " )
{
if ( ! _peer . expired ( ) )
forwardToPeer ( buffer , length ) ;
}
2015-09-09 12:23:49 -05:00
else if ( tokens [ 0 ] = = " commandvalues " )
{
return getCommandValues ( buffer , length , tokens ) ;
}
2015-09-29 05:27:45 -05:00
else if ( tokens [ 0 ] = = " partpagerectangles " )
{
return getPartPageRectangles ( buffer , length ) ;
}
2015-05-28 10:39:05 -05:00
else if ( tokens [ 0 ] = = " invalidatetiles " )
{
return invalidateTiles ( buffer , length , tokens ) ;
}
2015-03-04 17:14:04 -06:00
else if ( tokens [ 0 ] = = " status " )
{
2015-03-17 18:56:15 -05:00
return getStatus ( buffer , length ) ;
2015-03-04 17:14:04 -06:00
}
else if ( tokens [ 0 ] = = " tile " )
{
2015-03-17 18:56:15 -05:00
sendTile ( buffer , length , tokens ) ;
}
else
{
2015-03-20 08:50:23 -05:00
// All other commands are such that they always require a
// LibreOfficeKitDocument session, i.e. need to be handled in
// a child process.
2015-04-22 13:35:52 -05:00
if ( _peer . expired ( ) )
2015-04-20 09:43:31 -05:00
dispatchChild ( ) ;
2015-08-06 10:54:45 -05:00
if ( tokens [ 0 ] ! = " requestloksession " )
{
forwardToPeer ( buffer , length ) ;
}
2015-07-16 04:23:25 -05:00
2015-07-29 08:58:43 -05:00
if ( ( tokens . count ( ) > 1 & & tokens [ 0 ] = = " uno " & & tokens [ 1 ] = = " .uno:Save " ) ) {
2015-07-16 04:23:25 -05:00
_tileCache - > documentSaved ( ) ;
}
2015-04-20 09:43:31 -05:00
}
return true ;
}
bool MasterProcessSession : : haveSeparateProcess ( )
{
return _childId ! = 0 ;
}
2015-05-29 00:49:49 -05:00
Path MasterProcessSession : : getJailPath ( UInt64 childId )
2015-04-20 09:43:31 -05:00
{
return Path : : forDirectory ( LOOLWSD : : childRoot + Path : : separator ( ) + std : : to_string ( childId ) ) ;
}
2015-10-16 10:45:03 -05:00
bool MasterProcessSession : : invalidateTiles ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-05-28 10:39:05 -05:00
{
int part , tilePosX , tilePosY , tileWidth , tileHeight ;
if ( tokens . count ( ) ! = 6 | |
! getTokenInteger ( tokens [ 1 ] , " part " , part ) | |
! getTokenInteger ( tokens [ 2 ] , " tileposx " , tilePosX ) | |
! getTokenInteger ( tokens [ 3 ] , " tileposy " , tilePosY ) | |
! getTokenInteger ( tokens [ 4 ] , " tilewidth " , tileWidth ) | |
! getTokenInteger ( tokens [ 5 ] , " tileheight " , tileHeight ) )
{
sendTextFrame ( " error: cmd=invalidatetiles kind=syntax " ) ;
return false ;
}
2015-06-24 15:05:49 -05:00
// FIXME temporarily, set the editing on the 1st invalidate, TODO extend
// the protocol so that the client can set the editing or view only.
_tileCache - > setEditing ( true ) ;
2015-05-28 10:39:05 -05:00
_tileCache - > invalidateTiles ( _curPart , tilePosX , tilePosY , tileWidth , tileHeight ) ;
return true ;
}
2015-10-16 10:45:03 -05:00
bool MasterProcessSession : : loadDocument ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-04-20 09:43:31 -05:00
{
2015-11-18 11:09:13 -06:00
if ( tokens . count ( ) < 2 )
2015-04-20 09:43:31 -05:00
{
sendTextFrame ( " error: cmd=load kind=syntax " ) ;
return false ;
}
2015-11-18 11:09:13 -06:00
// First token is the "load" command itself.
size_t offset = 1 ;
if ( tokens . count ( ) > 2 & & tokens [ 1 ] . find ( " part= " ) = = 0 )
{
2015-08-26 23:18:44 -05:00
getTokenInteger ( tokens [ 1 ] , " part " , _loadPart ) ;
2015-11-18 11:09:13 -06:00
+ + offset ;
}
2015-08-26 23:18:44 -05:00
2015-08-04 13:37:05 -05:00
std : : string timestamp ;
2015-11-18 11:09:13 -06:00
for ( size_t i = offset ; i < tokens . count ( ) ; + + i )
2015-08-04 13:37:05 -05:00
{
if ( tokens [ i ] . find ( " url= " ) = = 0 )
2015-11-18 11:09:13 -06:00
{
2015-08-04 13:37:05 -05:00
_docURL = tokens [ i ] . substr ( strlen ( " url= " ) ) ;
2015-11-18 11:09:13 -06:00
+ + offset ;
}
2015-08-04 13:37:05 -05:00
else if ( tokens [ i ] . find ( " timestamp= " ) = = 0 )
2015-11-18 11:09:13 -06:00
{
2015-08-04 13:37:05 -05:00
timestamp = tokens [ i ] . substr ( strlen ( " timestamp= " ) ) ;
2015-11-18 11:09:13 -06:00
+ + offset ;
}
}
if ( tokens . count ( ) > offset )
{
if ( getTokenString ( tokens [ offset ] , " options " , _docOptions ) )
{
if ( tokens . count ( ) > offset + 1 )
_docOptions + = Poco : : cat ( std : : string ( " " ) , tokens . begin ( ) + offset + 1 , tokens . end ( ) ) ;
}
2015-08-04 13:37:05 -05:00
}
2015-04-20 09:43:31 -05:00
2015-07-04 19:46:13 -05:00
try
{
URI aUri ( _docURL ) ;
}
catch ( Poco : : SyntaxException & )
{
2015-08-11 11:31:50 -05:00
sendTextFrame ( " error: cmd=load kind=uriinvalid " ) ;
2015-07-04 19:46:13 -05:00
return false ;
}
2015-08-04 13:37:05 -05:00
_tileCache . reset ( new TileCache ( _docURL , timestamp ) ) ;
2015-04-20 09:43:31 -05:00
return true ;
}
bool MasterProcessSession : : getStatus ( const char * buffer , int length )
{
std : : string status ;
2015-08-18 13:01:05 -05:00
status = _tileCache - > getTextFile ( " status.txt " ) ;
2015-04-20 09:43:31 -05:00
if ( status . size ( ) > 0 )
{
sendTextFrame ( status ) ;
return true ;
}
2015-04-22 13:35:52 -05:00
if ( _peer . expired ( ) )
2015-04-20 09:43:31 -05:00
dispatchChild ( ) ;
forwardToPeer ( buffer , length ) ;
return true ;
}
2015-09-09 12:23:49 -05:00
bool MasterProcessSession : : getCommandValues ( const char * buffer , int length , StringTokenizer & tokens )
2015-08-18 13:01:05 -05:00
{
2015-09-09 12:23:49 -05:00
std : : string command ;
if ( tokens . count ( ) ! = 2 | | ! getTokenString ( tokens [ 1 ] , " command " , command ) )
{
sendTextFrame ( " error: cmd=commandvalues kind=syntax " ) ;
return false ;
}
2015-08-18 13:01:05 -05:00
2015-09-09 12:23:49 -05:00
std : : string cmdValues = _tileCache - > getTextFile ( " cmdValues " + command + " .txt " ) ;
if ( cmdValues . size ( ) > 0 )
2015-08-18 13:01:05 -05:00
{
2015-09-09 12:23:49 -05:00
sendTextFrame ( cmdValues ) ;
2015-08-18 13:01:05 -05:00
return true ;
}
if ( _peer . expired ( ) )
dispatchChild ( ) ;
forwardToPeer ( buffer , length ) ;
return true ;
}
2015-09-29 05:27:45 -05:00
bool MasterProcessSession : : getPartPageRectangles ( const char * buffer , int length )
{
std : : string partPageRectangles = _tileCache - > getTextFile ( " partpagerectangles.txt " ) ;
if ( partPageRectangles . size ( ) > 0 )
{
sendTextFrame ( partPageRectangles ) ;
return true ;
}
if ( _peer . expired ( ) )
dispatchChild ( ) ;
forwardToPeer ( buffer , length ) ;
return true ;
}
2015-10-20 07:03:31 -05:00
std : : string MasterProcessSession : : getSaveAs ( )
{
return _saveAsQueue . get ( ) ;
}
2015-04-20 09:43:31 -05:00
void MasterProcessSession : : sendTile ( const char * buffer , int length , StringTokenizer & tokens )
{
2015-04-27 13:24:05 -05:00
int part , width , height , tilePosX , tilePosY , tileWidth , tileHeight ;
2015-07-14 11:46:04 -05:00
if ( tokens . count ( ) < 8 | |
2015-04-27 13:24:05 -05:00
! getTokenInteger ( tokens [ 1 ] , " part " , part ) | |
! getTokenInteger ( tokens [ 2 ] , " width " , width ) | |
! getTokenInteger ( tokens [ 3 ] , " height " , height ) | |
! getTokenInteger ( tokens [ 4 ] , " tileposx " , tilePosX ) | |
! getTokenInteger ( tokens [ 5 ] , " tileposy " , tilePosY ) | |
! getTokenInteger ( tokens [ 6 ] , " tilewidth " , tileWidth ) | |
! getTokenInteger ( tokens [ 7 ] , " tileheight " , tileHeight ) )
2015-04-20 09:43:31 -05:00
{
sendTextFrame ( " error: cmd=tile kind=syntax " ) ;
return ;
}
2015-04-27 13:24:05 -05:00
if ( part < 0 | |
width < = 0 | |
2015-04-20 09:43:31 -05:00
height < = 0 | |
tilePosX < 0 | |
tilePosY < 0 | |
tileWidth < = 0 | |
tileHeight < = 0 )
{
sendTextFrame ( " error: cmd=tile kind=invalid " ) ;
return ;
}
std : : string response = " tile: " + Poco : : cat ( std : : string ( " " ) , tokens . begin ( ) + 1 , tokens . end ( ) ) + " \n " ;
std : : vector < char > output ;
output . reserve ( 4 * width * height ) ;
output . resize ( response . size ( ) ) ;
std : : memcpy ( output . data ( ) , response . data ( ) , response . size ( ) ) ;
2015-04-27 13:24:05 -05:00
std : : unique_ptr < std : : fstream > cachedTile = _tileCache - > lookupTile ( part , width , height , tilePosX , tilePosY , tileWidth , tileHeight ) ;
2015-04-20 09:43:31 -05:00
if ( cachedTile & & cachedTile - > is_open ( ) )
{
cachedTile - > seekg ( 0 , std : : ios_base : : end ) ;
size_t pos = output . size ( ) ;
std : : streamsize size = cachedTile - > tellg ( ) ;
output . resize ( pos + size ) ;
cachedTile - > seekg ( 0 , std : : ios_base : : beg ) ;
cachedTile - > read ( output . data ( ) + pos , size ) ;
cachedTile - > close ( ) ;
sendBinaryFrame ( output . data ( ) , output . size ( ) ) ;
return ;
}
2015-04-22 13:35:52 -05:00
if ( _peer . expired ( ) )
2015-04-20 09:43:31 -05:00
dispatchChild ( ) ;
forwardToPeer ( buffer , length ) ;
}
void MasterProcessSession : : dispatchChild ( )
{
// Copy document into jail using the fixed name
2015-05-07 08:29:36 -05:00
std : : shared_ptr < MasterProcessSession > childSession ;
std : : unique_lock < std : : mutex > lock ( _availableChildSessionMutex ) ;
2015-07-24 14:17:46 -05:00
std : : cout < < Util : : logPrefix ( ) < < " _availableChildSessions size= " < < _availableChildSessions . size ( ) < < std : : endl ;
2015-05-08 13:24:46 -05:00
2015-05-07 08:29:36 -05:00
if ( _availableChildSessions . size ( ) = = 0 )
{
std : : cout < < Util : : logPrefix ( ) < < " waiting for a child session to become available " < < std : : endl ;
_availableChildSessionCV . wait ( lock , [ ] { return _availableChildSessions . size ( ) > 0 ; } ) ;
std : : cout < < Util : : logPrefix ( ) < < " waiting done " < < std : : endl ;
}
2015-04-20 09:43:31 -05:00
2015-05-07 08:29:36 -05:00
childSession = * ( _availableChildSessions . begin ( ) ) ;
2015-04-20 09:43:31 -05:00
_availableChildSessions . erase ( childSession ) ;
2015-05-07 08:29:36 -05:00
lock . unlock ( ) ;
2015-04-20 09:43:31 -05:00
2015-08-05 19:01:39 -05:00
if ( _availableChildSessions . size ( ) = = 0 & & ! LOOLWSD : : doTest )
2015-08-05 17:19:51 -05:00
{
LOOLWSD : : _namedMutexLOOL . lock ( ) ;
std : : cout < < Util : : logPrefix ( ) < < " No available child sessions, queue new child session " < < std : : endl ;
LOOLWSD : : _sharedForkChild . begin ( ) [ 0 ] = ( LOOLWSD : : _sharedForkChild . begin ( ) [ 0 ] > 0 ? LOOLWSD : : _sharedForkChild . begin ( ) [ 0 ] + 1 : 1 ) ;
LOOLWSD : : _namedMutexLOOL . unlock ( ) ;
}
2015-07-04 19:46:13 -05:00
// Assume a valid URI
URI aUri ( _docURL ) ;
if ( aUri . isRelative ( ) )
aUri = URI ( URI ( " file:// " ) , aUri . toString ( ) ) ;
if ( ! aUri . empty ( ) & & aUri . getScheme ( ) = = " file " )
2015-04-30 07:58:13 -05:00
{
2015-07-17 15:55:49 -05:00
Path aSrcFile ( aUri . getPath ( ) ) ;
Path aDstFile ( Path ( getJailPath ( childSession - > _childId ) , jailDocumentURL . substr ( 1 ) ) , aSrcFile . getFileName ( ) ) ;
Path aDstPath ( getJailPath ( childSession - > _childId ) , jailDocumentURL . substr ( 1 ) ) ;
Path aJailFile ( jailDocumentURL , aSrcFile . getFileName ( ) ) ;
2015-07-03 09:01:47 -05:00
try
2015-05-12 04:28:46 -05:00
{
2015-07-17 15:55:49 -05:00
File ( aDstPath ) . createDirectories ( ) ;
2015-07-03 09:01:47 -05:00
}
2015-07-04 19:46:13 -05:00
catch ( Exception & exc )
2015-07-03 09:01:47 -05:00
{
2015-07-04 19:46:13 -05:00
Application : : instance ( ) . logger ( ) . error ( Util : : logPrefix ( ) +
2015-07-17 15:55:49 -05:00
" createDirectories( \" " + aDstPath . toString ( ) + " \" ) failed: " + exc . displayText ( ) ) ;
}
2015-11-05 05:15:54 -06:00
// cleanup potential leftovers from the last time
File aToCleanup ( aDstFile ) ;
if ( aToCleanup . exists ( ) )
aToCleanup . remove ( ) ;
2015-07-17 15:55:49 -05:00
# ifdef __linux
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + " Linking " + aSrcFile . toString ( ) + " to " + aDstFile . toString ( ) ) ;
if ( link ( aSrcFile . toString ( ) . c_str ( ) , aDstFile . toString ( ) . c_str ( ) ) = = - 1 )
{
// Failed
Application : : instance ( ) . logger ( ) . error ( Util : : logPrefix ( ) +
" link( \" " + aSrcFile . toString ( ) + " \" , \" " + aDstFile . toString ( ) + " \" ) failed: " + strerror ( errno ) ) ;
2015-07-04 19:46:13 -05:00
}
2015-07-17 15:55:49 -05:00
# endif
2015-07-04 19:46:13 -05:00
2015-07-17 15:55:49 -05:00
try
{
//fallback
if ( ! File ( aDstFile ) . exists ( ) )
{
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + " Copying " + aSrcFile . toString ( ) + " to " + aDstFile . toString ( ) ) ;
File ( aSrcFile ) . copyTo ( aDstFile . toString ( ) ) ;
}
}
catch ( Exception & exc )
{
Application : : instance ( ) . logger ( ) . error ( Util : : logPrefix ( ) +
" copyTo( \" " + aSrcFile . toString ( ) + " \" , \" " + aDstFile . toString ( ) + " \" ) failed: " + exc . displayText ( ) ) ;
}
2015-05-12 04:28:46 -05:00
}
2015-04-30 13:05:16 -05:00
2015-04-20 09:43:31 -05:00
_peer = childSession ;
2015-04-22 13:35:52 -05:00
childSession - > _peer = shared_from_this ( ) ;
2015-04-20 09:43:31 -05:00
2015-08-26 23:18:44 -05:00
std : : string loadRequest = " load " + ( _loadPart > = 0 ? " part= " + std : : to_string ( _loadPart ) : " " ) + " url= " + _docURL ;
2015-04-20 09:43:31 -05:00
forwardToPeer ( loadRequest . c_str ( ) , loadRequest . size ( ) ) ;
}
void MasterProcessSession : : forwardToPeer ( const char * buffer , int length )
{
2015-07-20 04:54:08 -05:00
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + _kindString + " ,forwardToPeer, " + getAbbreviatedMessage ( buffer , length ) ) ;
2015-04-22 13:35:52 -05:00
auto peer = _peer . lock ( ) ;
2015-04-30 10:44:27 -05:00
if ( ! peer )
return ;
2015-06-05 08:12:06 -05:00
peer - > sendBinaryFrame ( buffer , length ) ;
2015-04-20 09:43:31 -05:00
}
2015-03-20 08:50:23 -05:00
2015-10-09 07:55:49 -05:00
ChildProcessSession : : ChildProcessSession ( std : : shared_ptr < WebSocket > ws , LibreOfficeKit * loKit , std : : string childId ) :
2015-04-20 09:43:31 -05:00
LOOLSession ( ws , Kind : : ToMaster ) ,
2015-05-28 10:39:05 -05:00
_loKitDocument ( NULL ) ,
2015-07-21 08:56:02 -05:00
_loKit ( loKit ) ,
2015-10-09 07:55:49 -05:00
_childId ( childId ) ,
2015-07-21 08:56:02 -05:00
_clientPart ( 0 )
2015-04-20 09:43:31 -05:00
{
2015-05-28 08:42:38 -05:00
std : : cout < < Util : : logPrefix ( ) < < " ChildProcessSession ctor this= " < < this < < " ws= " < < _ws . get ( ) < < std : : endl ;
2015-04-20 09:43:31 -05:00
}
ChildProcessSession : : ~ ChildProcessSession ( )
{
std : : cout < < Util : : logPrefix ( ) < < " ChildProcessSession dtor this= " < < this < < std : : endl ;
2015-05-06 09:08:44 -05:00
if ( LIBREOFFICEKIT_HAS ( _loKit , registerCallback ) )
_loKit - > pClass - > registerCallback ( _loKit , 0 , 0 ) ;
2015-04-22 03:14:11 -05:00
Util : : shutdownWebSocket ( * _ws ) ;
2015-04-20 09:43:31 -05:00
}
2015-06-08 08:35:52 -05:00
bool ChildProcessSession : : handleInput ( const char * buffer , int length )
2015-04-20 09:43:31 -05:00
{
std : : string firstLine = getFirstLine ( buffer , length ) ;
StringTokenizer tokens ( firstLine , " " , StringTokenizer : : TOK_IGNORE_EMPTY | StringTokenizer : : TOK_TRIM ) ;
2015-07-20 04:54:08 -05:00
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + _kindString + " ,Input, " + getAbbreviatedMessage ( buffer , length ) ) ;
2015-04-20 09:43:31 -05:00
2015-11-09 15:20:26 -06:00
if ( tokens [ 0 ] = = " canceltiles " )
{
// this command makes sense only on the command queue level, nothing
// to do here
return true ;
}
else if ( tokens [ 0 ] = = " commandvalues " )
2015-09-09 12:23:49 -05:00
{
return getCommandValues ( buffer , length , tokens ) ;
}
2015-11-09 15:20:26 -06:00
else if ( tokens [ 0 ] = = " partpagerectangles " )
2015-09-29 05:27:45 -05:00
{
return getPartPageRectangles ( buffer , length ) ;
}
2015-11-09 15:20:26 -06:00
else if ( tokens [ 0 ] = = " load " )
2015-04-20 09:43:31 -05:00
{
if ( _docURL ! = " " )
{
sendTextFrame ( " error: cmd=load kind=docalreadyloaded " ) ;
return false ;
2015-03-20 08:50:23 -05:00
}
2015-04-20 09:43:31 -05:00
return loadDocument ( buffer , length , tokens ) ;
}
else if ( _docURL = = " " )
{
sendTextFrame ( " error: cmd= " + tokens [ 0 ] + " kind=nodocloaded " ) ;
return false ;
}
2015-07-21 08:56:02 -05:00
else if ( tokens [ 0 ] = = " setclientpart " )
{
return setClientPart ( buffer , length , tokens ) ;
}
2015-08-03 11:07:02 -05:00
else if ( tokens [ 0 ] = = " setpage " )
{
return setPage ( buffer , length , tokens ) ;
}
2015-04-20 09:43:31 -05:00
else if ( tokens [ 0 ] = = " status " )
{
return getStatus ( buffer , length ) ;
}
else if ( tokens [ 0 ] = = " tile " )
{
sendTile ( buffer , length , tokens ) ;
}
else
{
// All other commands are such that they always require a LibreOfficeKitDocument session,
// i.e. need to be handled in a child process.
2015-11-10 10:31:11 -06:00
assert ( tokens [ 0 ] = = " clientzoom " | |
tokens [ 0 ] = = " downloadas " | |
2015-10-22 10:32:19 -05:00
tokens [ 0 ] = = " getchildid " | |
2015-10-09 07:55:49 -05:00
tokens [ 0 ] = = " gettextselection " | |
2015-10-27 04:40:40 -05:00
tokens [ 0 ] = = " paste " | |
2015-10-22 10:32:19 -05:00
tokens [ 0 ] = = " insertfile " | |
2015-06-24 10:08:15 -05:00
tokens [ 0 ] = = " key " | |
2015-04-20 09:43:31 -05:00
tokens [ 0 ] = = " mouse " | |
tokens [ 0 ] = = " uno " | |
tokens [ 0 ] = = " selecttext " | |
tokens [ 0 ] = = " selectgraphic " | |
tokens [ 0 ] = = " resetselection " | |
tokens [ 0 ] = = " saveas " ) ;
2015-03-20 08:50:23 -05:00
2015-08-03 09:29:23 -05:00
if ( _docType ! = " text " & & _loKitDocument - > pClass - > getPart ( _loKitDocument ) ! = _clientPart )
2015-07-21 08:56:02 -05:00
{
_loKitDocument - > pClass - > setPart ( _loKitDocument , _clientPart ) ;
}
2015-11-10 10:31:11 -06:00
if ( tokens [ 0 ] = = " clientzoom " )
2015-10-22 10:32:19 -05:00
{
2015-11-10 10:31:11 -06:00
return clientZoom ( buffer , length , tokens ) ;
2015-10-22 10:32:19 -05:00
}
else if ( tokens [ 0 ] = = " downloadas " )
2015-10-09 07:55:49 -05:00
{
return downloadAs ( buffer , length , tokens ) ;
}
2015-11-10 10:31:11 -06:00
else if ( tokens [ 0 ] = = " getchildid " )
{
return getChildId ( ) ;
}
2015-10-09 07:55:49 -05:00
else if ( tokens [ 0 ] = = " gettextselection " )
2015-06-24 10:08:15 -05:00
{
return getTextSelection ( buffer , length , tokens ) ;
}
2015-10-27 04:40:40 -05:00
else if ( tokens [ 0 ] = = " paste " )
{
return paste ( buffer , length , tokens ) ;
}
2015-10-22 10:32:19 -05:00
else if ( tokens [ 0 ] = = " insertfile " )
{
return insertFile ( buffer , length , tokens ) ;
}
2015-06-24 10:08:15 -05:00
else if ( tokens [ 0 ] = = " key " )
2015-03-20 08:50:23 -05:00
{
return keyEvent ( buffer , length , tokens ) ;
}
else if ( tokens [ 0 ] = = " mouse " )
{
return mouseEvent ( buffer , length , tokens ) ;
}
else if ( tokens [ 0 ] = = " uno " )
{
return unoCommand ( buffer , length , tokens ) ;
}
else if ( tokens [ 0 ] = = " selecttext " )
{
return selectText ( buffer , length , tokens ) ;
}
else if ( tokens [ 0 ] = = " selectgraphic " )
{
return selectGraphic ( buffer , length , tokens ) ;
}
else if ( tokens [ 0 ] = = " resetselection " )
{
2015-03-23 15:13:57 -05:00
return resetSelection ( buffer , length , tokens ) ;
}
else if ( tokens [ 0 ] = = " saveas " )
{
return saveAs ( buffer , length , tokens ) ;
2015-03-20 08:50:23 -05:00
}
else
2015-04-20 09:43:31 -05:00
{
2015-03-20 08:50:23 -05:00
assert ( false ) ;
2015-04-20 09:43:31 -05:00
}
2015-03-04 17:14:04 -06:00
}
2015-03-07 05:23:46 -06:00
return true ;
2015-03-04 17:14:04 -06:00
}
2015-03-07 05:23:46 -06:00
extern " C "
{
static void myCallback ( int nType , const char * pPayload , void * pData )
{
2015-05-28 10:39:05 -05:00
ChildProcessSession * srv = reinterpret_cast < ChildProcessSession * > ( pData ) ;
2015-03-07 05:23:46 -06:00
switch ( ( LibreOfficeKitCallbackType ) nType )
{
case LOK_CALLBACK_INVALIDATE_TILES :
2015-05-29 01:44:39 -05:00
{
int curPart = srv - > _loKitDocument - > pClass - > getPart ( srv - > _loKitDocument ) ;
srv - > sendTextFrame ( " curpart: part= " + std : : to_string ( curPart ) ) ;
2015-08-03 09:29:23 -05:00
if ( srv - > _docType = = " text " )
{
curPart = 0 ;
}
2015-05-29 01:44:39 -05:00
StringTokenizer tokens ( std : : string ( pPayload ) , " " , StringTokenizer : : TOK_IGNORE_EMPTY | StringTokenizer : : TOK_TRIM ) ;
if ( tokens . count ( ) = = 4 )
{
2015-11-09 13:08:19 -06:00
int x , y , width , height ;
try {
x = std : : stoi ( tokens [ 0 ] ) ;
y = std : : stoi ( tokens [ 1 ] ) ;
width = std : : stoi ( tokens [ 2 ] ) ;
height = std : : stoi ( tokens [ 3 ] ) ;
}
catch ( std : : out_of_range & )
{
// something went wrong, invalidate everything
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + " Ignoring integer values out of range: " + pPayload ) ;
x = 0 ;
y = 0 ;
width = INT_MAX ;
height = INT_MAX ;
}
2015-07-20 12:10:13 -05:00
srv - > sendTextFrame ( " invalidatetiles: "
2015-05-29 01:44:39 -05:00
" part= " + std : : to_string ( curPart ) +
" x= " + std : : to_string ( x ) +
" y= " + std : : to_string ( y ) +
" width= " + std : : to_string ( width ) +
" height= " + std : : to_string ( height ) ) ;
}
2015-07-20 12:10:13 -05:00
else {
srv - > sendTextFrame ( " invalidatetiles: " + std : : string ( pPayload ) ) ;
}
2015-05-29 01:44:39 -05:00
}
2015-03-07 05:23:46 -06:00
break ;
case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR :
2015-05-24 23:40:08 -05:00
srv - > sendTextFrame ( " invalidatecursor: " + std : : string ( pPayload ) ) ;
2015-03-13 04:25:00 -05:00
break ;
2015-03-07 05:23:46 -06:00
case LOK_CALLBACK_TEXT_SELECTION :
srv - > sendTextFrame ( " textselection: " + std : : string ( pPayload ) ) ;
break ;
case LOK_CALLBACK_TEXT_SELECTION_START :
srv - > sendTextFrame ( " textselectionstart: " + std : : string ( pPayload ) ) ;
break ;
case LOK_CALLBACK_TEXT_SELECTION_END :
srv - > sendTextFrame ( " textselectionend: " + std : : string ( pPayload ) ) ;
break ;
2015-03-13 04:30:23 -05:00
case LOK_CALLBACK_CURSOR_VISIBLE :
srv - > sendTextFrame ( " cursorvisible: " + std : : string ( pPayload ) ) ;
break ;
case LOK_CALLBACK_GRAPHIC_SELECTION :
srv - > sendTextFrame ( " graphicselection: " + std : : string ( pPayload ) ) ;
2015-11-02 07:09:25 -06:00
break ;
case LOK_CALLBACK_CELL_CURSOR :
srv - > sendTextFrame ( " cellcursor: " + std : : string ( pPayload ) ) ;
2015-03-13 04:30:23 -05:00
break ;
2015-11-10 11:20:54 -06:00
case LOK_CALLBACK_CELL_FORMULA :
srv - > sendTextFrame ( " cellformula: " + std : : string ( pPayload ) ) ;
break ;
2015-11-10 04:42:56 -06:00
case LOK_CALLBACK_MOUSE_POINTER :
srv - > sendTextFrame ( " mousepointer: " + std : : string ( pPayload ) ) ;
2015-11-13 04:24:44 -06:00
break ;
2015-03-13 04:30:23 -05:00
case LOK_CALLBACK_HYPERLINK_CLICKED :
srv - > sendTextFrame ( " hyperlinkclicked: " + std : : string ( pPayload ) ) ;
break ;
2015-04-14 06:51:36 -05:00
case LOK_CALLBACK_STATE_CHANGED :
srv - > sendTextFrame ( " statechanged: " + std : : string ( pPayload ) ) ;
break ;
2015-05-06 09:08:44 -05:00
case LOK_CALLBACK_STATUS_INDICATOR_START :
srv - > sendTextFrame ( " statusindicatorstart: " ) ;
break ;
case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE :
srv - > sendTextFrame ( " statusindicatorsetvalue: " + std : : string ( pPayload ) ) ;
break ;
case LOK_CALLBACK_STATUS_INDICATOR_FINISH :
srv - > sendTextFrame ( " statusindicatorfinish: " ) ;
break ;
2015-05-19 03:56:04 -05:00
case LOK_CALLBACK_SEARCH_NOT_FOUND :
srv - > sendTextFrame ( " searchnotfound: " + std : : string ( pPayload ) ) ;
break ;
2015-10-06 09:33:22 -05:00
case LOK_CALLBACK_SEARCH_RESULT_SELECTION :
srv - > sendTextFrame ( " searchresultselection: " + std : : string ( pPayload ) ) ;
break ;
2015-05-27 10:34:10 -05:00
case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED :
2015-05-28 06:51:08 -05:00
srv - > getStatus ( " " , 0 ) ;
2015-09-30 09:22:00 -05:00
srv - > getPartPageRectangles ( " " , 0 ) ;
2015-05-23 05:26:11 -05:00
break ;
2015-05-27 04:36:05 -05:00
case LOK_CALLBACK_SET_PART :
srv - > sendTextFrame ( " setpart: " + std : : string ( pPayload ) ) ;
break ;
2015-11-03 12:28:46 -06:00
case LOK_CALLBACK_UNO_COMMAND_RESULT :
srv - > sendTextFrame ( " unocommandresult: " + std : : string ( pPayload ) ) ;
break ;
2015-03-07 05:23:46 -06:00
}
}
}
2015-04-20 09:43:31 -05:00
bool ChildProcessSession : : loadDocument ( const char * buffer , int length , StringTokenizer & tokens )
2015-03-04 17:14:04 -06:00
{
2015-08-26 23:18:44 -05:00
int part = - 1 ;
if ( tokens . count ( ) < 2 | | tokens . count ( ) > 4 )
2015-03-04 17:14:04 -06:00
{
sendTextFrame ( " error: cmd=load kind=syntax " ) ;
2015-03-17 18:56:15 -05:00
return false ;
2015-03-04 17:14:04 -06:00
}
2015-03-12 18:34:42 -05:00
2015-08-26 23:18:44 -05:00
if ( tokens . count ( ) > 2 & & tokens [ 2 ] . find ( " url= " ) = = 0 )
{
getTokenInteger ( tokens [ 1 ] , " part " , part ) ;
_docURL = tokens [ 2 ] . substr ( strlen ( " url= " ) ) ;
}
else if ( tokens [ 1 ] . find ( " url= " ) = = 0 )
2015-03-19 07:38:04 -05:00
_docURL = tokens [ 1 ] . substr ( strlen ( " url= " ) ) ;
else
_docURL = tokens [ 1 ] ;
2015-07-04 19:46:13 -05:00
URI aUri ;
try
{
aUri = URI ( _docURL ) ;
}
catch ( Poco : : SyntaxException & )
{
2015-08-11 11:31:50 -05:00
sendTextFrame ( " error: cmd=load kind=uriinvalid " ) ;
2015-07-04 19:46:13 -05:00
return false ;
}
if ( aUri . empty ( ) )
{
2015-08-11 11:31:50 -05:00
sendTextFrame ( " error: cmd=load kind=uriempty " ) ;
2015-07-04 19:46:13 -05:00
return false ;
}
2015-04-20 09:43:31 -05:00
// The URL in the request is the original one, not visible in the chroot jail.
// The child process uses the fixed name jailDocumentURL.
2015-04-10 04:20:42 -05:00
2015-05-06 09:08:44 -05:00
if ( LIBREOFFICEKIT_HAS ( _loKit , registerCallback ) )
_loKit - > pClass - > registerCallback ( _loKit , myCallback , this ) ;
2015-07-04 19:46:13 -05:00
if ( aUri . isRelative ( ) | | aUri . getScheme ( ) = = " file " )
aUri = URI ( URI ( " file:// " ) , Path ( jailDocumentURL , Path ( aUri . getPath ( ) ) . getFileName ( ) ) . toString ( ) ) ;
2015-07-03 09:01:47 -05:00
2015-07-04 19:46:13 -05:00
if ( ( _loKitDocument = _loKit - > pClass - > documentLoad ( _loKit , aUri . toString ( ) . c_str ( ) ) ) = = NULL )
2015-04-14 09:50:38 -05:00
{
2015-04-20 09:43:31 -05:00
sendTextFrame ( " error: cmd=load kind=failed " ) ;
2015-08-04 13:37:05 -05:00
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + " Failed to load: " + aUri . toString ( ) + " , error is: " + _loKit - > pClass - > getError ( _loKit ) ) ;
2015-04-20 09:43:31 -05:00
return false ;
2015-04-14 09:50:38 -05:00
}
2015-07-13 09:13:06 -05:00
2015-11-18 09:59:28 -06:00
_loKitDocument - > pClass - > initializeForRendering ( _loKitDocument , nullptr ) ;
2015-04-20 09:43:31 -05:00
2015-08-26 23:18:44 -05:00
if ( _docType ! = " text " & & part ! = - 1 )
{
_clientPart = part ;
_loKitDocument - > pClass - > setPart ( _loKitDocument , part ) ;
}
2015-04-20 09:43:31 -05:00
if ( ! getStatus ( buffer , length ) )
return false ;
2015-08-26 23:07:11 -05:00
2015-04-20 09:43:31 -05:00
_loKitDocument - > pClass - > registerCallback ( _loKitDocument , myCallback , this ) ;
2015-03-17 18:56:15 -05:00
return true ;
2015-03-04 17:14:04 -06:00
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : getStatus ( const char * /*buffer*/ , int /*length*/ )
2015-03-04 17:14:04 -06:00
{
2015-04-20 09:43:31 -05:00
std : : string status = " status: " + LOKitHelper : : documentStatus ( _loKitDocument ) ;
2015-08-03 09:29:23 -05:00
StringTokenizer tokens ( status , " " , StringTokenizer : : TOK_IGNORE_EMPTY | StringTokenizer : : TOK_TRIM ) ;
if ( ! getTokenString ( tokens [ 1 ] , " type " , _docType ) )
{
Application : : instance ( ) . logger ( ) . information ( Util : : logPrefix ( ) + " failed to get document type from " + status ) ;
}
2015-03-17 18:56:15 -05:00
sendTextFrame ( status ) ;
return true ;
2015-03-04 17:14:04 -06:00
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : getCommandValues ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-08-18 13:01:05 -05:00
{
2015-09-09 12:23:49 -05:00
std : : string command ;
if ( tokens . count ( ) ! = 2 | | ! getTokenString ( tokens [ 1 ] , " command " , command ) )
{
sendTextFrame ( " error: cmd=commandvalues kind=syntax " ) ;
return false ;
}
sendTextFrame ( " commandvalues: " + std : : string ( _loKitDocument - > pClass - > getCommandValues ( _loKitDocument , command . c_str ( ) ) ) ) ;
2015-08-18 13:01:05 -05:00
return true ;
}
2015-09-29 05:27:45 -05:00
bool ChildProcessSession : : getPartPageRectangles ( const char * /*buffer*/ , int /*length*/ )
{
sendTextFrame ( " partpagerectangles: " + std : : string ( _loKitDocument - > pClass - > getPartPageRectangles ( _loKitDocument ) ) ) ;
return true ;
}
2015-10-16 10:45:03 -05:00
void ChildProcessSession : : sendTile ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-04 17:14:04 -06:00
{
2015-04-27 13:24:05 -05:00
int part , width , height , tilePosX , tilePosY , tileWidth , tileHeight ;
2015-07-14 11:46:04 -05:00
if ( tokens . count ( ) < 8 | |
2015-04-27 13:24:05 -05:00
! getTokenInteger ( tokens [ 1 ] , " part " , part ) | |
! getTokenInteger ( tokens [ 2 ] , " width " , width ) | |
! getTokenInteger ( tokens [ 3 ] , " height " , height ) | |
! getTokenInteger ( tokens [ 4 ] , " tileposx " , tilePosX ) | |
! getTokenInteger ( tokens [ 5 ] , " tileposy " , tilePosY ) | |
! getTokenInteger ( tokens [ 6 ] , " tilewidth " , tileWidth ) | |
! getTokenInteger ( tokens [ 7 ] , " tileheight " , tileHeight ) )
2015-03-04 17:14:04 -06:00
{
sendTextFrame ( " error: cmd=tile kind=syntax " ) ;
return ;
}
2015-04-27 13:24:05 -05:00
if ( part < 0 | |
width < = 0 | |
2015-03-24 11:59:04 -05:00
height < = 0 | |
tilePosX < 0 | |
tilePosY < 0 | |
tileWidth < = 0 | |
tileHeight < = 0 )
{
sendTextFrame ( " error: cmd=tile kind=invalid " ) ;
return ;
}
2015-03-12 09:18:35 -05:00
std : : string response = " tile: " + Poco : : cat ( std : : string ( " " ) , tokens . begin ( ) + 1 , tokens . end ( ) ) + " \n " ;
std : : vector < char > output ;
output . reserve ( 4 * width * height ) ;
output . resize ( response . size ( ) ) ;
2015-04-09 17:25:48 -05:00
std : : memcpy ( output . data ( ) , response . data ( ) , response . size ( ) ) ;
2015-03-12 09:18:35 -05:00
2015-03-17 18:56:15 -05:00
unsigned char * pixmap = new unsigned char [ 4 * width * height ] ;
2015-08-03 09:29:23 -05:00
if ( _docType ! = " text " & & part ! = _loKitDocument - > pClass - > getPart ( _loKitDocument ) ) {
_loKitDocument - > pClass - > setPart ( _loKitDocument , part ) ;
}
2015-11-06 06:33:11 -06:00
Poco : : Timestamp timestamp ;
2015-03-20 06:16:41 -05:00
_loKitDocument - > pClass - > paintTile ( _loKitDocument , pixmap , width , height , tilePosX , tilePosY , tileWidth , tileHeight ) ;
2015-11-06 06:33:11 -06:00
std : : cout < < Util : : logPrefix ( ) < < " paintTile called, tile at [ " < < tilePosX < < " , " < < tilePosY < < " ] rendered in " < < double ( timestamp . elapsed ( ) ) / 1000 < < " ms " < < std : : endl ;
2015-03-04 17:14:04 -06:00
2015-03-28 06:53:44 -05:00
if ( ! Util : : encodePNGAndAppendToBuffer ( pixmap , width , height , output ) )
2015-03-04 17:14:04 -06:00
{
sendTextFrame ( " error: cmd=tile kind=failure " ) ;
return ;
}
2015-03-17 18:56:15 -05:00
delete [ ] pixmap ;
2015-03-04 17:14:04 -06:00
sendBinaryFrame ( output . data ( ) , output . size ( ) ) ;
}
2015-11-10 10:31:11 -06:00
bool ChildProcessSession : : clientZoom ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
{
int tilePixelWidth , tilePixelHeight , tileTwipWidth , tileTwipHeight ;
if ( tokens . count ( ) ! = 5 | |
! getTokenInteger ( tokens [ 1 ] , " tilepixelwidth " , tilePixelWidth ) | |
! getTokenInteger ( tokens [ 2 ] , " tilepixelheight " , tilePixelHeight ) | |
! getTokenInteger ( tokens [ 3 ] , " tiletwipwidth " , tileTwipWidth ) | |
! getTokenInteger ( tokens [ 4 ] , " tiletwipheight " , tileTwipHeight ) )
{
sendTextFrame ( " error: cmd=clientzoom kind=syntax " ) ;
return false ;
}
_loKitDocument - > pClass - > setClientZoom ( _loKitDocument , tilePixelWidth , tilePixelHeight , tileTwipWidth , tileTwipHeight ) ;
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : downloadAs ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-10-09 07:55:49 -05:00
{
2015-10-09 09:20:18 -05:00
std : : string name , id , format , filterOptions ;
2015-10-09 07:55:49 -05:00
2015-10-16 11:27:13 -05:00
if ( tokens . count ( ) < 5 | |
2015-10-09 09:20:18 -05:00
! getTokenString ( tokens [ 1 ] , " name " , name ) | |
2015-10-16 11:27:13 -05:00
! getTokenString ( tokens [ 2 ] , " id " , id ) )
2015-10-09 07:55:49 -05:00
{
2015-10-13 12:56:42 -05:00
sendTextFrame ( " error: cmd=downloadas kind=syntax " ) ;
2015-10-09 07:55:49 -05:00
return false ;
}
2015-10-16 11:27:13 -05:00
getTokenString ( tokens [ 3 ] , " format " , format ) ;
2015-10-09 07:55:49 -05:00
2015-10-16 11:27:13 -05:00
if ( getTokenString ( tokens [ 4 ] , " options " , filterOptions ) ) {
if ( tokens . count ( ) > 5 ) {
filterOptions + = Poco : : cat ( std : : string ( " " ) , tokens . begin ( ) + 5 , tokens . end ( ) ) ;
2015-10-09 07:55:49 -05:00
}
}
std : : string tmpDir , url ;
File * file = NULL ;
do
{
if ( file ! = NULL )
{
delete file ;
}
tmpDir = std : : to_string ( ( ( ( Poco : : UInt64 ) LOOLWSD : : _rng . next ( ) ) < < 32 ) | LOOLWSD : : _rng . next ( ) | 1 ) ;
url = jailDocumentURL + " / " + tmpDir + " / " + name ;
file = new File ( url ) ;
} while ( file - > exists ( ) ) ;
delete file ;
_loKitDocument - > pClass - > saveAs ( _loKitDocument , url . c_str ( ) ,
format . size ( ) = = 0 ? NULL : format . c_str ( ) ,
filterOptions . size ( ) = = 0 ? NULL : filterOptions . c_str ( ) ) ;
sendTextFrame ( " downloadas: jail= " + _childId + " dir= " + tmpDir + " name= " + name +
2015-10-16 11:27:13 -05:00
" port= " + std : : to_string ( LOOLWSD : : portNumber ) + " id= " + id ) ;
2015-10-09 07:55:49 -05:00
return true ;
}
2015-10-22 10:32:19 -05:00
bool ChildProcessSession : : getChildId ( )
{
sendTextFrame ( " getchildid: id= " + _childId ) ;
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : getTextSelection ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-06-24 10:08:15 -05:00
{
std : : string mimeType ;
if ( tokens . count ( ) ! = 2 | |
! getTokenString ( tokens [ 1 ] , " mimetype " , mimeType ) )
{
sendTextFrame ( " error: cmd=gettextselection kind=syntax " ) ;
return false ;
}
char * textSelection = _loKitDocument - > pClass - > getTextSelection ( _loKitDocument , mimeType . c_str ( ) , NULL ) ;
sendTextFrame ( " textselectioncontent: " + std : : string ( textSelection ) ) ;
return true ;
}
2015-10-27 04:40:40 -05:00
bool ChildProcessSession : : paste ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
{
std : : string mimeType ;
std : : string data ;
if ( tokens . count ( ) < 3 | | ! getTokenString ( tokens [ 1 ] , " mimetype " , mimeType ) | | ! getTokenString ( tokens [ 2 ] , " data " , data ) )
{
sendTextFrame ( " error: cmd=paste kind=syntax " ) ;
return false ;
}
data = Poco : : cat ( std : : string ( " " ) , tokens . begin ( ) + 2 , tokens . end ( ) ) . substr ( strlen ( " data= " ) ) ;
_loKitDocument - > pClass - > paste ( _loKitDocument , mimeType . c_str ( ) , data . c_str ( ) , std : : strlen ( data . c_str ( ) ) ) ;
return true ;
}
2015-10-22 10:32:19 -05:00
bool ChildProcessSession : : insertFile ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
{
std : : string name , type ;
if ( tokens . count ( ) ! = 3 | |
! getTokenString ( tokens [ 1 ] , " name " , name ) ,
! getTokenString ( tokens [ 2 ] , " type " , type ) )
{
sendTextFrame ( " error: cmd=insertfile kind=syntax " ) ;
return false ;
}
if ( type = = " graphic " ) {
std : : string fileName = " file:// " + jailDocumentURL + " /insertfile/ " + name ;
std : : string command = " .uno:InsertGraphic " ;
std : : string arguments = " { "
" \" FileName \" :{ "
" \" type \" : \" string \" , "
" \" value \" : \" " + fileName + " \" "
" }} " ;
2015-11-03 12:28:46 -06:00
_loKitDocument - > pClass - > postUnoCommand ( _loKitDocument , command . c_str ( ) , arguments . c_str ( ) , false ) ;
2015-10-22 10:32:19 -05:00
}
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : keyEvent ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-19 07:38:04 -05:00
{
int type , charcode , keycode ;
if ( tokens . count ( ) ! = 4 | |
2015-04-27 13:09:27 -05:00
! getTokenKeyword ( tokens [ 1 ] , " type " ,
{ { " input " , LOK_KEYEVENT_KEYINPUT } , { " up " , LOK_KEYEVENT_KEYUP } } ,
type ) | |
2015-03-26 09:49:07 -05:00
! getTokenInteger ( tokens [ 2 ] , " char " , charcode ) | |
! getTokenInteger ( tokens [ 3 ] , " key " , keycode ) )
2015-03-19 07:38:04 -05:00
{
sendTextFrame ( " error: cmd=key kind=syntax " ) ;
return false ;
}
_loKitDocument - > pClass - > postKeyEvent ( _loKitDocument , type , charcode , keycode ) ;
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : mouseEvent ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-19 07:38:04 -05:00
{
2015-10-05 07:04:19 -05:00
int type , x , y , count , buttons , modifier ;
2015-03-19 07:38:04 -05:00
2015-10-05 07:04:19 -05:00
if ( tokens . count ( ) ! = 7 | |
2015-04-27 13:09:27 -05:00
! getTokenKeyword ( tokens [ 1 ] , " type " ,
{ { " buttondown " , LOK_MOUSEEVENT_MOUSEBUTTONDOWN } ,
{ " buttonup " , LOK_MOUSEEVENT_MOUSEBUTTONUP } ,
{ " move " , LOK_MOUSEEVENT_MOUSEMOVE } } ,
type ) | |
2015-03-26 09:49:07 -05:00
! getTokenInteger ( tokens [ 2 ] , " x " , x ) | |
! getTokenInteger ( tokens [ 3 ] , " y " , y ) | |
2015-10-05 07:04:19 -05:00
! getTokenInteger ( tokens [ 4 ] , " count " , count ) ,
! getTokenInteger ( tokens [ 5 ] , " buttons " , buttons ) ,
! getTokenInteger ( tokens [ 6 ] , " modifier " , modifier ) )
2015-03-19 07:38:04 -05:00
{
sendTextFrame ( " error: cmd=mouse kind=syntax " ) ;
return false ;
}
2015-10-05 07:04:19 -05:00
_loKitDocument - > pClass - > postMouseEvent ( _loKitDocument , type , x , y , count , buttons , modifier ) ;
2015-03-19 07:38:04 -05:00
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : unoCommand ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-19 07:38:04 -05:00
{
if ( tokens . count ( ) = = 1 )
{
sendTextFrame ( " error: cmd=uno kind=syntax " ) ;
return false ;
}
2015-11-03 12:28:46 -06:00
// we need to get LOK_CALLBACK_UNO_COMMAND_RESULT callback when saving
bool bNotify = ( tokens [ 1 ] = = " .uno:Save " ) ;
2015-07-08 01:09:58 -05:00
if ( tokens . count ( ) = = 2 )
{
2015-11-03 12:28:46 -06:00
_loKitDocument - > pClass - > postUnoCommand ( _loKitDocument , tokens [ 1 ] . c_str ( ) , 0 , bNotify ) ;
2015-07-08 01:09:58 -05:00
}
else
{
2015-11-03 12:28:46 -06:00
_loKitDocument - > pClass - > postUnoCommand ( _loKitDocument , tokens [ 1 ] . c_str ( ) , Poco : : cat ( std : : string ( " " ) , tokens . begin ( ) + 2 , tokens . end ( ) ) . c_str ( ) , bNotify ) ;
2015-07-08 01:09:58 -05:00
}
2015-03-19 07:38:04 -05:00
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : selectText ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-19 07:38:04 -05:00
{
int type , x , y ;
2015-03-26 09:49:07 -05:00
if ( tokens . count ( ) ! = 4 | |
2015-04-27 13:09:27 -05:00
! getTokenKeyword ( tokens [ 1 ] , " type " ,
{ { " start " , LOK_SETTEXTSELECTION_START } ,
{ " end " , LOK_SETTEXTSELECTION_END } ,
{ " reset " , LOK_SETTEXTSELECTION_RESET } } ,
type ) | |
2015-03-26 09:49:07 -05:00
! getTokenInteger ( tokens [ 2 ] , " x " , x ) | |
! getTokenInteger ( tokens [ 3 ] , " y " , y ) )
2015-03-19 07:38:04 -05:00
{
sendTextFrame ( " error: cmd=selecttext kind=syntax " ) ;
return false ;
}
_loKitDocument - > pClass - > setTextSelection ( _loKitDocument , type , x , y ) ;
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : selectGraphic ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-19 07:38:04 -05:00
{
int type , x , y ;
if ( tokens . count ( ) ! = 4 | |
2015-04-27 13:09:27 -05:00
! getTokenKeyword ( tokens [ 1 ] , " type " ,
{ { " start " , LOK_SETGRAPHICSELECTION_START } ,
{ " end " , LOK_SETGRAPHICSELECTION_END } } ,
type ) | |
2015-03-26 09:49:07 -05:00
! getTokenInteger ( tokens [ 2 ] , " x " , x ) | |
! getTokenInteger ( tokens [ 3 ] , " y " , y ) )
2015-03-19 07:38:04 -05:00
{
2015-08-11 11:39:18 -05:00
sendTextFrame ( " error: cmd=selectgraphic kind=syntax " ) ;
2015-03-19 07:38:04 -05:00
return false ;
}
_loKitDocument - > pClass - > setGraphicSelection ( _loKitDocument , type , x , y ) ;
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : resetSelection ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-19 07:38:04 -05:00
{
2015-03-20 07:56:37 -05:00
if ( tokens . count ( ) ! = 1 )
{
sendTextFrame ( " error: cmd=resetselection kind=syntax " ) ;
return false ;
}
2015-03-19 07:38:04 -05:00
_loKitDocument - > pClass - > resetSelection ( _loKitDocument ) ;
2015-03-20 07:56:37 -05:00
return true ;
2015-03-19 07:38:04 -05:00
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : saveAs ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-03-23 15:13:57 -05:00
{
std : : string url , format , filterOptions ;
if ( tokens . count ( ) < 4 | |
2015-07-16 04:00:27 -05:00
! getTokenString ( tokens [ 1 ] , " url " , url ) )
2015-03-23 15:13:57 -05:00
{
sendTextFrame ( " error: cmd=saveas kind=syntax " ) ;
return false ;
}
2015-07-29 03:39:35 -05:00
getTokenString ( tokens [ 2 ] , " format " , format ) ;
2015-03-23 15:13:57 -05:00
2015-07-16 04:00:27 -05:00
if ( getTokenString ( tokens [ 3 ] , " options " , filterOptions ) ) {
if ( tokens . count ( ) > 4 ) {
filterOptions + = Poco : : cat ( std : : string ( " " ) , tokens . begin ( ) + 4 , tokens . end ( ) ) ;
}
}
2015-03-23 15:13:57 -05:00
2015-07-29 03:39:35 -05:00
_loKitDocument - > pClass - > saveAs ( _loKitDocument , url . c_str ( ) ,
format . size ( ) = = 0 ? NULL : format . c_str ( ) ,
filterOptions . size ( ) = = 0 ? NULL : filterOptions . c_str ( ) ) ;
2015-03-23 15:13:57 -05:00
2015-10-20 07:03:31 -05:00
sendTextFrame ( " saveas: url= " + url ) ;
2015-03-23 15:13:57 -05:00
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : setClientPart ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-07-21 08:56:02 -05:00
{
if ( tokens . count ( ) < 2 | |
! getTokenInteger ( tokens [ 1 ] , " part " , _clientPart ) )
{
return false ;
}
return true ;
}
2015-10-16 10:45:03 -05:00
bool ChildProcessSession : : setPage ( const char * /*buffer*/ , int /*length*/ , StringTokenizer & tokens )
2015-08-03 11:07:02 -05:00
{
int page ;
if ( tokens . count ( ) < 2 | |
! getTokenInteger ( tokens [ 1 ] , " page " , page ) )
{
sendTextFrame ( " error: cmd=setpage kind=invalid " ) ;
return false ;
}
_loKitDocument - > pClass - > setPart ( _loKitDocument , page ) ;
return true ;
}
2015-03-04 17:14:04 -06:00
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */