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-26 09:49:07 -05: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/.
|
|
|
|
*/
|
|
|
|
|
2016-11-24 08:56:06 -06:00
|
|
|
#include "Protocol.hpp"
|
loolwsd: include cleanup and organization
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-05-21 09:23:07 -05:00
|
|
|
#include "config.h"
|
|
|
|
|
2015-03-26 09:49:07 -05:00
|
|
|
#include <cassert>
|
2015-04-14 09:50:38 -05:00
|
|
|
#include <cstring>
|
2015-04-27 13:09:27 -05:00
|
|
|
#include <map>
|
|
|
|
#include <string>
|
2015-03-26 09:49:07 -05:00
|
|
|
|
|
|
|
#define LOK_USE_UNSTABLE_API
|
|
|
|
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
|
|
|
|
|
|
|
|
#include <Poco/StringTokenizer.h>
|
|
|
|
|
|
|
|
using Poco::StringTokenizer;
|
|
|
|
|
|
|
|
namespace LOOLProtocol
|
|
|
|
{
|
2016-02-23 02:22:18 -06:00
|
|
|
std::tuple<int, int, std::string> ParseVersion(const std::string& version)
|
2016-01-06 11:00:44 -06:00
|
|
|
{
|
2016-02-23 02:22:18 -06:00
|
|
|
int major = -1;
|
|
|
|
int minor = -1;
|
2016-01-06 11:00:44 -06:00
|
|
|
std::string patch;
|
|
|
|
|
|
|
|
StringTokenizer firstTokens(version, ".", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
|
|
|
if (firstTokens.count() > 0)
|
|
|
|
{
|
|
|
|
major = std::stoi(firstTokens[0]);
|
|
|
|
|
|
|
|
StringTokenizer secondTokens(firstTokens[1], "-", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
|
|
|
minor = std::stoi(secondTokens[0]);
|
|
|
|
|
|
|
|
if (secondTokens.count() > 1)
|
|
|
|
patch = secondTokens[1];
|
|
|
|
}
|
|
|
|
return std::make_tuple(major, minor, patch);
|
|
|
|
}
|
|
|
|
|
2016-01-12 05:07:13 -06:00
|
|
|
bool stringToInteger(const std::string& input, int& value)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
value = std::stoi(input);
|
|
|
|
}
|
|
|
|
catch (std::invalid_argument&)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-03-26 09:49:07 -05:00
|
|
|
bool getTokenInteger(const std::string& token, const std::string& name, int& value)
|
|
|
|
{
|
|
|
|
size_t nextIdx;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (token.size() < name.size() + 2 ||
|
|
|
|
token.substr(0, name.size()) != name ||
|
|
|
|
token[name.size()] != '=' ||
|
|
|
|
(value = std::stoi(token.substr(name.size() + 1), &nextIdx), false) ||
|
|
|
|
nextIdx != token.size() - name.size() - 1)
|
|
|
|
{
|
2016-05-15 16:44:40 -05:00
|
|
|
return false;
|
2015-03-26 09:49:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::invalid_argument&)
|
|
|
|
{
|
2015-04-27 13:09:27 -05:00
|
|
|
return false;
|
2015-03-26 09:49:07 -05:00
|
|
|
}
|
2015-04-27 13:09:27 -05:00
|
|
|
|
2015-03-26 09:49:07 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getTokenString(const std::string& token, const std::string& name, std::string& value)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (token.size() < name.size() + 2 ||
|
|
|
|
token.substr(0, name.size()) != name ||
|
|
|
|
token[name.size()] != '=')
|
|
|
|
{
|
2016-05-15 16:44:40 -05:00
|
|
|
return false;
|
2015-03-26 09:49:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (std::invalid_argument&)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-15 16:44:40 -05:00
|
|
|
|
2015-03-26 09:49:07 -05:00
|
|
|
value = token.substr(name.size() + 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-27 13:09:27 -05:00
|
|
|
bool getTokenKeyword(const std::string& token, const std::string& name, const std::map<std::string, int>& map, int& value)
|
|
|
|
{
|
|
|
|
if (token.size() < name.size() + 2 ||
|
|
|
|
token.substr(0, name.size()) != name ||
|
|
|
|
token[name.size()] != '=')
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::string t = token.substr(name.size()+1);
|
|
|
|
if (t[0] == '\'' && t[t.size()-1] == '\'')
|
|
|
|
t = t.substr(1, t.size()-2);
|
|
|
|
|
|
|
|
auto p = map.find(t);
|
|
|
|
if (p == map.cend())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
value = p->second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-04-20 08:44:12 -05:00
|
|
|
bool getTokenInteger(const Poco::StringTokenizer& tokens, const std::string& name, int& value)
|
|
|
|
{
|
2016-04-20 14:47:00 -05:00
|
|
|
for (size_t i = 0; i < tokens.count(); i++)
|
2016-04-20 08:44:12 -05:00
|
|
|
{
|
|
|
|
if (getTokenInteger(tokens[i], name, value))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getTokenString(const Poco::StringTokenizer& tokens, const std::string& name, std::string& value)
|
|
|
|
{
|
2016-04-20 14:47:00 -05:00
|
|
|
for (size_t i = 0; i < tokens.count(); i++)
|
2016-04-20 08:44:12 -05:00
|
|
|
{
|
|
|
|
if (getTokenString(tokens[i], name, value))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getTokenKeyword(const Poco::StringTokenizer& tokens, const std::string& name, const std::map<std::string, int>& map, int& value)
|
|
|
|
{
|
2016-04-20 14:47:00 -05:00
|
|
|
for (size_t i = 0; i < tokens.count(); i++)
|
2016-04-20 08:44:12 -05:00
|
|
|
{
|
|
|
|
if (getTokenKeyword(tokens[i], name, map, value))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-26 11:31:19 -05:00
|
|
|
bool getTokenIntegerFromMessage(const std::string& message, const std::string& name, int& value)
|
|
|
|
{
|
2016-10-21 10:54:15 -05:00
|
|
|
Poco::StringTokenizer tokens(message, " \n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
2016-09-26 11:31:19 -05:00
|
|
|
return getTokenInteger(tokens, name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getTokenStringFromMessage(const std::string& message, const std::string& name, std::string& value)
|
|
|
|
{
|
2016-10-21 10:54:15 -05:00
|
|
|
Poco::StringTokenizer tokens(message, " \n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
2016-09-26 11:31:19 -05:00
|
|
|
return getTokenString(tokens, name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getTokenKeywordFromMessage(const std::string& message, const std::string& name, const std::map<std::string, int>& map, int& value)
|
|
|
|
{
|
2016-10-21 10:54:15 -05:00
|
|
|
Poco::StringTokenizer tokens(message, " \n", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
2016-09-26 11:31:19 -05:00
|
|
|
return getTokenKeyword(tokens, name, map, value);
|
|
|
|
}
|
|
|
|
|
2015-03-26 09:49:07 -05:00
|
|
|
bool parseStatus(const std::string& message, LibreOfficeKitDocumentType& type, int& nParts, int& currentPart, int& width, int& height)
|
|
|
|
{
|
|
|
|
StringTokenizer tokens(message, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
|
|
|
|
|
|
|
assert(tokens.count() == 6);
|
|
|
|
assert(tokens[0] == "status:");
|
|
|
|
|
|
|
|
std::string typeString;
|
|
|
|
if (!getTokenString(tokens[1], "type", typeString))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (typeString == "text")
|
|
|
|
type = LOK_DOCTYPE_TEXT;
|
|
|
|
else if (typeString == "spreadsheet")
|
|
|
|
type = LOK_DOCTYPE_SPREADSHEET;
|
|
|
|
else if (typeString == "presentation")
|
|
|
|
type = LOK_DOCTYPE_PRESENTATION;
|
|
|
|
else if (typeString == "drawing")
|
|
|
|
type = LOK_DOCTYPE_PRESENTATION;
|
|
|
|
else if (typeString == "other")
|
|
|
|
type = LOK_DOCTYPE_OTHER;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!getTokenInteger(tokens[2], "parts", nParts) ||
|
|
|
|
!getTokenInteger(tokens[3], "current", currentPart) ||
|
|
|
|
!getTokenInteger(tokens[4], "width", width) ||
|
|
|
|
!getTokenInteger(tokens[5], "height", height))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|