2018-09-11 01:30:55 -05:00
|
|
|
// -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*-
|
|
|
|
//
|
|
|
|
// 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/.
|
|
|
|
|
|
|
|
#import "config.h"
|
|
|
|
|
2018-09-13 11:16:00 -05:00
|
|
|
#import <algorithm>
|
|
|
|
|
Call comphelper::LibreOfficeKit::setLanguageTag() to avoid assertion failure
The locale / language tag dance is a bit confusing. Let's hope it now
works sanely.
Without this change, if I as a test in Xcode set the LANG environment
variable when running the app to "de", to match the case where the
user is using their device in a German locale, and then open a
non-trivial .odt document, close it, and open it again, I get an
assertion failure in sw, in SwXPageStyle::GetPropertyValues_Impl().
(Note that the LANG environment variable is not set by the system on
iOS; in this app LANG is just an arbitrary (but familiar) name for an
environment variable used only when debugging in Xcode. Maybe I should
have called it something else to avoid confusing code readers who
might think it has the same meaning as in POSIX systems.)
The above assertion failure does not happen if I don't set LANG. I
don't really fully understand the convoluted mechanisms involved, but
explicitly re-setting the <comphelper/lok.hxx> concept of (global)
language tag each time before opening a document seems to help. Note
that if I set LANG to just "de", the code then later while handling
setView() calls in ChildSession::loadDocument(), sets it to "de-DE"
anyway. But that doesn't seem to harm.
Change-Id: Ic697ed44b4ace488782ebee3aa2e7610bb02e93c
2018-11-12 07:17:24 -06:00
|
|
|
// This is not "external" code in the UNO-based extensions sense. To be able to include
|
|
|
|
// <comphelper/lok.hxx>, we must #define LIBO_INTERNAL_ONLY.
|
|
|
|
|
|
|
|
#define LIBO_INTERNAL_ONLY
|
|
|
|
#include <sal/config.h>
|
2018-11-12 12:13:23 -06:00
|
|
|
#include <sal/log.hxx>
|
Call comphelper::LibreOfficeKit::setLanguageTag() to avoid assertion failure
The locale / language tag dance is a bit confusing. Let's hope it now
works sanely.
Without this change, if I as a test in Xcode set the LANG environment
variable when running the app to "de", to match the case where the
user is using their device in a German locale, and then open a
non-trivial .odt document, close it, and open it again, I get an
assertion failure in sw, in SwXPageStyle::GetPropertyValues_Impl().
(Note that the LANG environment variable is not set by the system on
iOS; in this app LANG is just an arbitrary (but familiar) name for an
environment variable used only when debugging in Xcode. Maybe I should
have called it something else to avoid confusing code readers who
might think it has the same meaning as in POSIX systems.)
The above assertion failure does not happen if I don't set LANG. I
don't really fully understand the convoluted mechanisms involved, but
explicitly re-setting the <comphelper/lok.hxx> concept of (global)
language tag each time before opening a document seems to help. Note
that if I set LANG to just "de", the code then later while handling
setView() calls in ChildSession::loadDocument(), sets it to "de-DE"
anyway. But that doesn't seem to harm.
Change-Id: Ic697ed44b4ace488782ebee3aa2e7610bb02e93c
2018-11-12 07:17:24 -06:00
|
|
|
#include <rtl/ustring.hxx>
|
|
|
|
#include <comphelper/lok.hxx>
|
|
|
|
#include <i18nlangtag/languagetag.hxx>
|
|
|
|
|
2018-09-13 11:16:00 -05:00
|
|
|
#import "ios.h"
|
2018-09-11 01:30:55 -05:00
|
|
|
#import "AppDelegate.h"
|
|
|
|
#import "Document.h"
|
|
|
|
#import "DocumentViewController.h"
|
|
|
|
|
2018-09-13 11:16:00 -05:00
|
|
|
#import "ClientSession.hpp"
|
|
|
|
#import "DocumentBroker.hpp"
|
|
|
|
#import "FakeSocket.hpp"
|
2018-09-11 01:30:55 -05:00
|
|
|
#import "Kit.hpp"
|
|
|
|
#import "KitHelper.hpp"
|
|
|
|
#import "Log.hpp"
|
2018-09-13 11:16:00 -05:00
|
|
|
#import "LOOLWSD.hpp"
|
2018-09-11 01:30:55 -05:00
|
|
|
#import "Protocol.hpp"
|
|
|
|
|
|
|
|
@implementation Document
|
|
|
|
|
|
|
|
- (id)contentsForType:(NSString*)typeName error:(NSError **)errorPtr {
|
2018-11-27 05:18:24 -06:00
|
|
|
// Somehow this doesn't feel right, creating an NSFileWrapper around the file that was given to
|
|
|
|
// us for loadFromContents. I get the vague feeling that the file is perhaps just a temporary
|
|
|
|
// data container created by the system for us to be used while loading the document data, and
|
|
|
|
// not the actual permanent document, especially in the case of things like NextCloud. Or is it?
|
|
|
|
// Is savng back to it (which we have already done by the time we get here, in the LO core code)
|
|
|
|
// correct? This does seem to work, though. Anyway, clearly I need to read more documentation
|
|
|
|
// for UIDocument etc.
|
|
|
|
return [[NSFileWrapper alloc] initWithURL:[self fileURL] options:0 error:errorPtr];
|
2018-09-11 01:30:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)errorPtr {
|
2018-09-13 11:16:00 -05:00
|
|
|
fakeClientFd = fakeSocketSocket();
|
2018-11-09 15:33:55 -06:00
|
|
|
NSString *uri = [[self fileURL] absoluteString];
|
|
|
|
|
2018-12-10 11:46:52 -06:00
|
|
|
comphelper::LibreOfficeKit::setLanguageTag(LanguageTag(OUString::fromUtf8(OString([app_locale UTF8String])), true));
|
Call comphelper::LibreOfficeKit::setLanguageTag() to avoid assertion failure
The locale / language tag dance is a bit confusing. Let's hope it now
works sanely.
Without this change, if I as a test in Xcode set the LANG environment
variable when running the app to "de", to match the case where the
user is using their device in a German locale, and then open a
non-trivial .odt document, close it, and open it again, I get an
assertion failure in sw, in SwXPageStyle::GetPropertyValues_Impl().
(Note that the LANG environment variable is not set by the system on
iOS; in this app LANG is just an arbitrary (but familiar) name for an
environment variable used only when debugging in Xcode. Maybe I should
have called it something else to avoid confusing code readers who
might think it has the same meaning as in POSIX systems.)
The above assertion failure does not happen if I don't set LANG. I
don't really fully understand the convoluted mechanisms involved, but
explicitly re-setting the <comphelper/lok.hxx> concept of (global)
language tag each time before opening a document seems to help. Note
that if I set LANG to just "de", the code then later while handling
setView() calls in ChildSession::loadDocument(), sets it to "de-DE"
anyway. But that doesn't seem to harm.
Change-Id: Ic697ed44b4ace488782ebee3aa2e7610bb02e93c
2018-11-12 07:17:24 -06:00
|
|
|
|
2018-09-13 11:16:00 -05:00
|
|
|
NSURL *url = [[NSBundle mainBundle] URLForResource:@"loleaflet" withExtension:@"html"];
|
|
|
|
NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
|
2018-11-09 15:33:55 -06:00
|
|
|
components.queryItems = @[ [NSURLQueryItem queryItemWithName:@"file_path" value:uri],
|
2018-10-12 09:48:45 -05:00
|
|
|
[NSURLQueryItem queryItemWithName:@"closebutton" value:@"1"],
|
2018-11-09 15:33:55 -06:00
|
|
|
[NSURLQueryItem queryItemWithName:@"permission" value:@"edit"],
|
2018-12-10 11:46:52 -06:00
|
|
|
[NSURLQueryItem queryItemWithName:@"lang" value:app_locale]
|
2018-11-09 15:33:55 -06:00
|
|
|
];
|
|
|
|
|
2018-09-13 11:16:00 -05:00
|
|
|
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:components.URL];
|
|
|
|
[self.viewController.webView loadRequest:request];
|
2018-09-11 01:30:55 -05:00
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)send2JS:(const char *)buffer length:(int)length {
|
2018-11-06 09:39:38 -06:00
|
|
|
LOG_TRC("To JS: " << LOOLProtocol::getAbbreviatedMessage(buffer, length).c_str());
|
2018-09-11 01:30:55 -05:00
|
|
|
|
|
|
|
NSString *js;
|
|
|
|
|
2018-09-13 11:16:00 -05:00
|
|
|
// Check if the message is binary. We say that any message that isn't just a single line is
|
|
|
|
// "binary" even if that strictly speaking isn't the case; for instance the commandvalues:
|
|
|
|
// message has a long bunch of non-binary JSON on multiple lines. But _onMessage() in Socket.js
|
|
|
|
// handles it fine even if such a message, too, comes in as an ArrayBuffer. (Look for the
|
|
|
|
// "textMsg = String.fromCharCode.apply(null, imgBytes);".)
|
|
|
|
|
|
|
|
const char *newline = (const char *)memchr(buffer, '\n', length);
|
|
|
|
if (newline != nullptr) {
|
|
|
|
// The data needs to be an ArrayBuffer
|
|
|
|
js = @"window.TheFakeWebSocket.onmessage({'data': Base64ToArrayBuffer('";
|
|
|
|
js = [js stringByAppendingString: [[NSData dataWithBytes:buffer length:length] base64EncodedStringWithOptions:0]];
|
|
|
|
js = [js stringByAppendingString:@"')});"];
|
2018-11-28 17:01:12 -06:00
|
|
|
NSString *subjs = [js substringToIndex:std::min(100ul, js.length)];
|
2018-11-28 16:23:17 -06:00
|
|
|
if (subjs.length < js.length)
|
|
|
|
subjs = [subjs stringByAppendingString:@"..."];
|
2018-09-13 11:16:00 -05:00
|
|
|
|
2018-11-06 09:39:38 -06:00
|
|
|
// LOG_TRC("Evaluating JavaScript: " << [subjs UTF8String]);
|
2018-09-11 01:30:55 -05:00
|
|
|
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self.viewController.webView evaluateJavaScript:js
|
|
|
|
completionHandler:^(id _Nullable obj, NSError * _Nullable error)
|
|
|
|
{
|
|
|
|
if (error) {
|
2018-11-06 09:39:38 -06:00
|
|
|
LOG_ERR("Error after " << [subjs UTF8String] << ": " << [error.localizedDescription UTF8String]);
|
2018-09-11 01:30:55 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
2018-09-13 11:16:00 -05:00
|
|
|
});
|
2018-09-11 01:30:55 -05:00
|
|
|
} else {
|
2018-09-13 11:16:00 -05:00
|
|
|
const unsigned char *ubufp = (const unsigned char *)buffer;
|
|
|
|
std::vector<char> data;
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
if (ubufp[i] < ' ' || ubufp[i] == '\'' || ubufp[i] == '\\') {
|
|
|
|
data.push_back('\\');
|
|
|
|
data.push_back('x');
|
|
|
|
data.push_back("0123456789abcdef"[(ubufp[i] >> 4) & 0x0F]);
|
|
|
|
data.push_back("0123456789abcdef"[ubufp[i] & 0x0F]);
|
|
|
|
} else {
|
|
|
|
data.push_back(ubufp[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
data.push_back(0);
|
|
|
|
|
|
|
|
js = @"window.TheFakeWebSocket.onmessage({'data': '";
|
|
|
|
js = [js stringByAppendingString:[NSString stringWithUTF8String:data.data()]];
|
|
|
|
js = [js stringByAppendingString:@"'});"];
|
|
|
|
|
2018-11-06 09:39:38 -06:00
|
|
|
// LOG_TRC("Evaluating JavaScript: " << [js UTF8String]);
|
2018-09-13 11:16:00 -05:00
|
|
|
|
2018-09-11 01:30:55 -05:00
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self.viewController.webView evaluateJavaScript:js
|
|
|
|
completionHandler:^(id _Nullable obj, NSError * _Nullable error)
|
|
|
|
{
|
|
|
|
if (error) {
|
2018-11-06 09:39:38 -06:00
|
|
|
LOG_ERR("Error after " << [js UTF8String] << ": " << [error.userInfo[@"WKJavaScriptExceptionMessage"] UTF8String]);
|
2018-09-11 01:30:55 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
// vim:set shiftwidth=4 softtabstop=4 expandtab:
|