[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 9 commits - cui/source cui/uiconfig desktop/qa desktop/source include/svl include/unotools officecfg/registry sfx2/source svl/CppunitTest_svl_lockfiles.mk svl/Library_svl.mk svl/Module_svl.mk svl/qa svl/source sw/source unotools/source
Tamás Zolnai (via logerrit)
logerrit at kemper.freedesktop.org
Thu Jun 20 12:32:51 UTC 2019
cui/source/options/optfltr.cxx | 10
cui/source/options/optfltr.hxx | 1
cui/uiconfig/ui/optfltrembedpage.ui | 63 +
desktop/qa/desktop_app/test_desktop_app.cxx | 23
desktop/source/app/cmdlineargs.cxx | 10
include/svl/documentlockfile.hxx | 39
include/svl/lockfilecommon.hxx | 21
include/svl/msodocumentlockfile.hxx | 86 +
include/svl/sharecontrolfile.hxx | 2
include/unotools/fltrcfg.hxx | 3
officecfg/registry/schema/org/openoffice/Office/Common.xcs | 8
sfx2/source/doc/docfile.cxx | 132 +-
sfx2/source/doc/objstor.cxx | 14
svl/CppunitTest_svl_lockfiles.mk | 52
svl/Library_svl.mk | 3
svl/Module_svl.mk | 1
svl/qa/unit/lockfiles/test_lockfiles.cxx | 712 +++++++++++++
svl/source/misc/documentlockfile.cxx | 140 +-
svl/source/misc/lockfilecommon.cxx | 37
svl/source/misc/msodocumentlockfile.cxx | 263 ++++
svl/source/misc/sharecontrolfile.cxx | 6
sw/source/core/layout/fly.cxx | 5
sw/source/ui/config/optcomp.cxx | 26
sw/source/uibase/docvw/FloatingTableButton.cxx | 9
sw/source/uibase/docvw/FrameControlsManager.cxx | 4
sw/source/uibase/inc/FloatingTableButton.hxx | 4
sw/source/uibase/inc/FrameControlsManager.hxx | 2
unotools/source/config/fltrcfg.cxx | 27
28 files changed, 1497 insertions(+), 206 deletions(-)
New commits:
commit 82c7ecc4852a6ff39343a43f91c410bd72d2b702
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Sun Apr 28 15:21:39 2019 +0200
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:21 2019 +0200
WebDav: Don't unlock the file during saving of a document
Otherwise it can happen that the file is locked by someone
else during the saving method is running.
I just extended the scope of the existing DisableUnlockWebDAV()
calls a bit. In case of webdav it does not cause an issue to
avoid unlocking the file before locking it again with an other
SfxMedium.
Change-Id: I6ac4e3326c63c9e184a7710ce8994cac1ed79449
Reviewed-on: https://gerrit.libreoffice.org/71484
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit fdab153636ad7e3ce4b09836a63d2fa11b42e728)
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 61e94cfc1c94..59293e3e9cb1 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -1187,6 +1187,10 @@ bool SfxObjectShell::SaveTo_Impl
&& !rMedium.GetName().equalsIgnoreAsciiCase("private:stream")
&& ::utl::UCBContentHelper::EqualURLs( pMedium->GetName(), rMedium.GetName() ) )
{
+ // Do not unlock the file during saving.
+ // need to modify this for WebDAV if this method is called outside of
+ // the process of saving a file
+ pMedium->DisableUnlockWebDAV();
bStoreToSameLocation = true;
if ( pMedium->DocNeedsFileDateCheck() )
@@ -1287,6 +1291,7 @@ bool SfxObjectShell::SaveTo_Impl
}
}
}
+ pMedium->DisableUnlockWebDAV(false);
}
else
{
@@ -1706,10 +1711,6 @@ bool SfxObjectShell::SaveTo_Impl
return bOk;
}
-
-// This method contains a call to disable the UNLOCK of a WebDAV resource, that work while saving a file.
-// If the method is called from another process (e.g. not when saving a file),
-// that disabling needs tweaking
bool SfxObjectShell::DisconnectStorage_Impl( SfxMedium& rSrcMedium, SfxMedium& rTargetMedium )
{
// this method disconnects the storage from source medium, and attaches it to the backup created by the target medium
@@ -1730,12 +1731,7 @@ bool SfxObjectShell::DisconnectStorage_Impl( SfxMedium& rSrcMedium, SfxMedium& r
rTargetMedium.ResetError();
xOptStorage->writeAndAttachToStream( uno::Reference< io::XStream >() );
rSrcMedium.CanDisposeStorage_Impl( false );
- // need to modify this for WebDAV if this method is called outside
- // the process of saving a file
- rSrcMedium.DisableUnlockWebDAV();
rSrcMedium.Close();
- // see comment on the previous third row
- rSrcMedium.DisableUnlockWebDAV( false );
// now try to create the backup
rTargetMedium.GetBackup_Impl();
commit 32f7ecd68f8d64fa4651ba9efd82feaa4448a8d5
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Apr 17 12:33:13 2019 +0200
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:21 2019 +0200
SharePoint connection: Better handling of encoded URLs
Handle %7c with small letters.
Make sure that the output parameter's content is not
affected by decoding.
Change-Id: Ie3faad2461815497c0edfb04a589fc57aeb7d66b
Reviewed-on: https://gerrit.libreoffice.org/70873
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit f6dc5636c1eda8aebeac3f7b85dd61499523d6a3)
diff --git a/desktop/qa/desktop_app/test_desktop_app.cxx b/desktop/qa/desktop_app/test_desktop_app.cxx
index 055c8cf5434e..1a027dfade78 100644
--- a/desktop/qa/desktop_app/test_desktop_app.cxx
+++ b/desktop/qa/desktop_app/test_desktop_app.cxx
@@ -113,7 +113,7 @@ void Test::testTdf100837() {
{
// 3. Test enocded URLs
- TestSupplier supplier{ "foo", "ms-word:ofe%7Cu%7Cbar1", "ms-word:ofv%7Cu%7Cbar2", "ms-word:nft%7Cu%7Cbar3", "baz" };
+ TestSupplier supplier{ "foo", "ms-word:ofe%7Cu%7cbar1", "ms-word:ofv%7cu%7Cbar2", "ms-word:nft%7Cu%7cbar3", "baz" };
desktop::CommandLineArgs args(supplier);
auto vOpenList = args.GetOpenList();
auto vForceOpenList = args.GetForceOpenList();
diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx
old mode 100755
new mode 100644
index acb266eb335e..30d0c3f4cced
--- a/desktop/source/app/cmdlineargs.cxx
+++ b/desktop/source/app/cmdlineargs.cxx
@@ -131,25 +131,25 @@ CommandLineEvent CheckOfficeURI(/* in,out */ OUString& arg, CommandLineEvent cur
long nURIlen = -1;
// URL might be encoded
- rest1 = rest1.replaceAll("%7C", "|");
+ OUString decoded_rest = rest1.replaceAll("%7C", "|").replaceAll("%7c", "|");
// 2. Discriminate by command name (incl. 1st command argument descriptor)
// Extract URI: everything up to possible next argument
- if (rest1.startsWith("ofv|u|", &rest2))
+ if (decoded_rest.startsWith("ofv|u|", &rest2))
{
// Open for view - override only in default mode
if (curEvt == CommandLineEvent::Open)
curEvt = CommandLineEvent::View;
nURIlen = rest2.indexOf("|");
}
- else if (rest1.startsWith("ofe|u|", &rest2))
+ else if (decoded_rest.startsWith("ofe|u|", &rest2))
{
// Open for editing - override only in default mode
if (curEvt == CommandLineEvent::Open)
curEvt = CommandLineEvent::ForceOpen;
nURIlen = rest2.indexOf("|");
}
- else if (rest1.startsWith("nft|u|", &rest2))
+ else if (decoded_rest.startsWith("nft|u|", &rest2))
{
// New from template - override only in default mode
if (curEvt == CommandLineEvent::Open)
commit f6c469e82cff213413584b3a4face70dcb3ede17
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Tue Apr 16 10:45:12 2019 +0200
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:21 2019 +0200
SharePoint connection: Handle encoded URL passed as command line argument
Change-Id: I3352bf9ade88bd86f7ca3d53238364216547d52b
Reviewed-on: https://gerrit.libreoffice.org/70830
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit 2317ad572cc330c4c2de95065ef275f58a9c83a1)
diff --git a/desktop/qa/desktop_app/test_desktop_app.cxx b/desktop/qa/desktop_app/test_desktop_app.cxx
index ef588a580266..055c8cf5434e 100644
--- a/desktop/qa/desktop_app/test_desktop_app.cxx
+++ b/desktop/qa/desktop_app/test_desktop_app.cxx
@@ -110,6 +110,29 @@ void Test::testTdf100837() {
CPPUNIT_ASSERT_EQUAL(OUString("bar"), vForceOpenList[0]);
CPPUNIT_ASSERT_EQUAL(OUString("baz"), vForceOpenList[1]);
}
+
+ {
+ // 3. Test enocded URLs
+ TestSupplier supplier{ "foo", "ms-word:ofe%7Cu%7Cbar1", "ms-word:ofv%7Cu%7Cbar2", "ms-word:nft%7Cu%7Cbar3", "baz" };
+ desktop::CommandLineArgs args(supplier);
+ auto vOpenList = args.GetOpenList();
+ auto vForceOpenList = args.GetForceOpenList();
+ auto vViewList = args.GetViewList();
+ auto vForceNewList = args.GetForceNewList();
+ // 2 documents go to Open list: foo; baz
+ CPPUNIT_ASSERT_EQUAL(decltype(vOpenList.size())(2), vOpenList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("foo"), vOpenList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("baz"), vOpenList[1]);
+ // 1 document goes to ForceOpen list: bar1
+ CPPUNIT_ASSERT_EQUAL(decltype(vForceOpenList.size())(1), vForceOpenList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar1"), vForceOpenList[0]);
+ // 1 document goes to View list: bar2
+ CPPUNIT_ASSERT_EQUAL(decltype(vViewList.size())(1), vViewList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar2"), vViewList[0]);
+ // 1 document goes to ForceNew list: bar3
+ CPPUNIT_ASSERT_EQUAL(decltype(vForceNewList.size())(1), vForceNewList.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar3"), vForceNewList[0]);
+ }
}
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx
old mode 100644
new mode 100755
index 52f96dd84d88..acb266eb335e
--- a/desktop/source/app/cmdlineargs.cxx
+++ b/desktop/source/app/cmdlineargs.cxx
@@ -129,6 +129,10 @@ CommandLineEvent CheckOfficeURI(/* in,out */ OUString& arg, CommandLineEvent cur
OUString rest2;
long nURIlen = -1;
+
+ // URL might be encoded
+ rest1 = rest1.replaceAll("%7C", "|");
+
// 2. Discriminate by command name (incl. 1st command argument descriptor)
// Extract URI: everything up to possible next argument
if (rest1.startsWith("ofv|u|", &rest2))
commit 46e970b3bf8fe9ed1df94649a0e1cd23ba3ffce1
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Sat Apr 6 13:25:27 2019 +0200
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:21 2019 +0200
respect read-only config item: MSCompatibleFormsMenu
Change-Id: I4eacbe8ad2025a54c13f4c0fa06e30e5ab59b721
Reviewed-on: https://gerrit.libreoffice.org/70344
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit 1ac1fdbe5bb3139c81a331beb16c79e84d7c4f27)
diff --git a/sw/source/ui/config/optcomp.cxx b/sw/source/ui/config/optcomp.cxx
index 1a74d382a7ca..1876bb87fd19 100644
--- a/sw/source/ui/config/optcomp.cxx
+++ b/sw/source/ui/config/optcomp.cxx
@@ -37,6 +37,8 @@
#include <vector>
#include <svtools/restartdialog.hxx>
#include <comphelper/processfactory.hxx>
+#include <officecfg/Office/Compatibility.hxx>
+#include <vcl/svlbitm.hxx>
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::document;
@@ -82,11 +84,31 @@ SwCompatibilityOptPage::SwCompatibilityOptPage(vcl::Window* pParent, const SfxIt
m_pOptionsLB->SetStyle( m_pOptionsLB->GetStyle() | WB_HSCROLL | WB_HIDESELECTION );
m_pOptionsLB->SetHighlightRange();
- SvTreeListEntry* pEntry = m_pGlobalOptionsCLB->SvTreeListBox::InsertEntry( m_pGlobalOptionsLB->GetEntry( 0 ) );
+
+ // Set MSOCompatibleFormsMenu entry attributes
+ const bool bReadOnly = officecfg::Office::Compatibility::View::MSCompatibleFormsMenu::isReadOnly();
+ const bool bChecked = m_aViewConfigItem.HasMSOCompatibleFormsMenu();
+
+ SvTreeListEntry* pEntry;
+ if(bReadOnly)
+ {
+ pEntry = m_pGlobalOptionsCLB->SvTreeListBox::InsertEntry( m_pGlobalOptionsLB->GetEntry( 0 ), nullptr, false,
+ TREELIST_APPEND, nullptr, SvLBoxButtonKind::DisabledCheckbox);
+ }
+ else
+ {
+ pEntry = m_pGlobalOptionsCLB->SvTreeListBox::InsertEntry( m_pGlobalOptionsLB->GetEntry( 0 ) );
+ }
+
if ( pEntry )
{
- m_pGlobalOptionsCLB->SetCheckButtonState( pEntry, SvButtonState::Unchecked );
+ SvLBoxButton* pButton = static_cast<SvLBoxButton*>(pEntry->GetFirstItem(SvLBoxItemType::Button));
+ if(bChecked)
+ pButton->SetStateChecked();
+ else
+ pButton->SetStateUnchecked();
}
+
m_pGlobalOptionsLB->Clear();
m_pGlobalOptionsCLB->SetStyle( m_pGlobalOptionsCLB->GetStyle() | WB_HSCROLL | WB_HIDESELECTION );
commit 9ba0d45530d6316492a85bca08a51cee2d6a0041
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Wed Apr 3 18:05:40 2019 +0200
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:21 2019 +0200
svl.lockfiles.test: Create the temporary lock files in workdir
Change-Id: I98b03754259c296ec8b4de2dddf6aee611bfe68a
Reviewed-on: https://gerrit.libreoffice.org/70209
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit 413461e3cf3a4b32a17419f67f879a8975c43987)
diff --git a/svl/qa/unit/lockfiles/test_lockfiles.cxx b/svl/qa/unit/lockfiles/test_lockfiles.cxx
index 5f23240f387c..b6c110ed6e48 100644
--- a/svl/qa/unit/lockfiles/test_lockfiles.cxx
+++ b/svl/qa/unit/lockfiles/test_lockfiles.cxx
@@ -29,6 +29,8 @@ namespace
{
class LockfileTest : public test::BootstrapFixture
{
+ OUString generateTestURL(const OUString& sFileName) const;
+
public:
void testLOLockFileURL();
void testLOLockFileContent();
@@ -92,11 +94,15 @@ OUString GetLockFileName(const svt::GenDocumentLockFile& rLockFile)
return aDocURL.GetName();
}
+OUString LockfileTest::generateTestURL(const OUString& sFileName) const
+{
+ return m_directories.getURLFromWorkdir("/CppunitTest/svl_lockfiles.test.user/") + sFileName;
+}
+
void LockfileTest::testLOLockFileURL()
{
// Test the generated file name for LibreOffice lock files
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileURL.odt");
+ OUString aTestODT = generateTestURL("testLOLockFileURL.odt");
svt::DocumentLockFile aLockFile(aTestODT);
CPPUNIT_ASSERT_EQUAL(OUString(".~lock.testLOLockFileURL.odt%23"), GetLockFileName(aLockFile));
@@ -105,8 +111,7 @@ void LockfileTest::testLOLockFileURL()
void LockfileTest::testLOLockFileContent()
{
// Test the lockfile generated for the specified ODT document
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileContent.odt");
+ OUString aTestODT = generateTestURL("testLOLockFileContent.odt");
// Set user name
SvtUserOptions aUserOpt;
@@ -157,8 +162,7 @@ void LockfileTest::testLOLockFileContent()
void LockfileTest::testLOLockFileRT()
{
// Test the lockfile generated for the specified ODT document
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileRT.odt");
+ OUString aTestODT = generateTestURL("testLOLockFileRT.odt");
// Set user name
SvtUserOptions aUserOpt;
@@ -188,8 +192,7 @@ void LockfileTest::testLOLockFileRT()
void LockfileTest::testLOLockFileUnicodeUsername()
{
// Test the lockfile generated for the specified ODT document
- OUString aTestODT = m_directories.getURLFromSrc(
- "/svl/qa/unit/lockfiles/data/testLOLockFileUnicodeUsername.odt");
+ OUString aTestODT = generateTestURL("testLOLockFileUnicodeUsername.odt");
// Set user name
SvtUserOptions aUserOpt;
@@ -215,8 +218,7 @@ void LockfileTest::testLOLockFileUnicodeUsername()
void LockfileTest::testLOLockFileOverwrite()
{
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileOverwrite.odt");
+ OUString aTestODT = generateTestURL("testLOLockFileOverwrite.odt");
// Set user name
SvtUserOptions aUserOpt;
@@ -257,62 +259,56 @@ void LockfileTest::testWordLockFileURL()
// Word specific file format
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testWordLockFileURL.docx");
+ OUString aTestFile = generateTestURL("testWordLockFileURL.docx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$stWordLockFileURL.docx"), GetLockFileName(aLockFile));
}
// Eight character file name (cuts two characters)
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.docx");
+ OUString aTestFile = generateTestURL("12345678.docx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$345678.docx"), GetLockFileName(aLockFile));
}
// Seven character file name (cuts one character)
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1234567.docx");
+ OUString aTestFile = generateTestURL("1234567.docx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$234567.docx"), GetLockFileName(aLockFile));
}
// Six character file name (cuts no character)
{
- OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/123456.docx");
+ OUString aTestFile = generateTestURL("123456.docx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$123456.docx"), GetLockFileName(aLockFile));
}
// One character file name
{
- OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1.docx");
+ OUString aTestFile = generateTestURL("1.docx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$1.docx"), GetLockFileName(aLockFile));
}
// Test for ODT format
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.odt");
+ OUString aTestFile = generateTestURL("12345678.odt");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$345678.odt"), GetLockFileName(aLockFile));
}
// Test for DOC format
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.doc");
+ OUString aTestFile = generateTestURL("12345678.doc");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$345678.doc"), GetLockFileName(aLockFile));
}
// Test for RTF format
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.rtf");
+ OUString aTestFile = generateTestURL("12345678.rtf");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$345678.rtf"), GetLockFileName(aLockFile));
}
@@ -322,31 +318,28 @@ void LockfileTest::testExcelLockFileURL()
{
// Test the generated file name for Excel lock files
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testExcelLockFileURL.xlsx");
+ OUString aTestFile = generateTestURL("testExcelLockFileURL.xlsx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$testExcelLockFileURL.xlsx"), GetLockFileName(aLockFile));
}
// Eight character file name
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.xlsx");
+ OUString aTestFile = generateTestURL("12345678.xlsx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.xlsx"), GetLockFileName(aLockFile));
}
// One character file name
{
- OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1.xlsx");
+ OUString aTestFile = generateTestURL("1.xlsx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$1.xlsx"), GetLockFileName(aLockFile));
}
// Test for ODS format
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.ods");
+ OUString aTestFile = generateTestURL("12345678.ods");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.ods"), GetLockFileName(aLockFile));
}
@@ -356,8 +349,7 @@ void LockfileTest::testPowerPointLockFileURL()
{
// Test the generated file name for PowerPoint lock files
{
- OUString aTestFile = m_directories.getURLFromSrc(
- "/svl/qa/unit/lockfiles/data/testPowerPointLockFileURL.pptx");
+ OUString aTestFile = generateTestURL("testPowerPointLockFileURL.pptx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$testPowerPointLockFileURL.pptx"),
GetLockFileName(aLockFile));
@@ -365,31 +357,28 @@ void LockfileTest::testPowerPointLockFileURL()
// Eight character file name
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.pptx");
+ OUString aTestFile = generateTestURL("12345678.pptx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.pptx"), GetLockFileName(aLockFile));
}
// One character file name
{
- OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1.pptx");
+ OUString aTestFile = generateTestURL("1.pptx");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$1.pptx"), GetLockFileName(aLockFile));
}
// Test for PPT format
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.ppt");
+ OUString aTestFile = generateTestURL("12345678.ppt");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.ppt"), GetLockFileName(aLockFile));
}
// Test for ODP format
{
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.odp");
+ OUString aTestFile = generateTestURL("/12345678.odp");
svt::MSODocumentLockFile aLockFile(aTestFile);
CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.odp"), GetLockFileName(aLockFile));
}
@@ -398,8 +387,7 @@ void LockfileTest::testPowerPointLockFileURL()
void LockfileTest::testWordLockFileContent()
{
// Test the lockfile generated for the specified DOCX document
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testWordLockFileContent.docx");
+ OUString aTestFile = generateTestURL("testWordLockFileContent.docx");
// Set user name
SvtUserOptions aUserOpt;
@@ -453,8 +441,7 @@ void LockfileTest::testWordLockFileContent()
void LockfileTest::testExcelLockFileContent()
{
// Test the lockfile generated for the specified XLSX document
- OUString aTestFile
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testExcelLockFileContent.xlsx");
+ OUString aTestFile = generateTestURL("testExcelLockFileContent.xlsx");
// Set user name
SvtUserOptions aUserOpt;
@@ -513,8 +500,7 @@ void LockfileTest::testExcelLockFileContent()
void LockfileTest::testPowerPointLockFileContent()
{
// Test the lockfile generated for the specified PPTX document
- OUString aTestFile = m_directories.getURLFromSrc(
- "/svl/qa/unit/lockfiles/data/testPowerPointLockFileContent.pptx");
+ OUString aTestFile = generateTestURL("testPowerPointLockFileContent.pptx");
// Set user name
SvtUserOptions aUserOpt;
@@ -574,8 +560,7 @@ void LockfileTest::testPowerPointLockFileContent()
void LockfileTest::testWordLockFileRT()
{
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testWordLockFileRT.docx");
+ OUString aTestODT = generateTestURL("testWordLockFileRT.docx");
// Set user name
SvtUserOptions aUserOpt;
@@ -596,8 +581,7 @@ void LockfileTest::testWordLockFileRT()
void LockfileTest::testExcelLockFileRT()
{
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testExcelLockFileRT.xlsx");
+ OUString aTestODT = generateTestURL("testExcelLockFileRT.xlsx");
// Set user name
SvtUserOptions aUserOpt;
@@ -618,8 +602,7 @@ void LockfileTest::testExcelLockFileRT()
void LockfileTest::testPowerPointLockFileRT()
{
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testPowerPointLockFileRT.pptx");
+ OUString aTestODT = generateTestURL("testPowerPointLockFileRT.pptx");
// Set user name
SvtUserOptions aUserOpt;
@@ -640,8 +623,7 @@ void LockfileTest::testPowerPointLockFileRT()
void LockfileTest::testMSOLockFileLongUserName()
{
- OUString aTestODT = m_directories.getURLFromSrc(
- "/svl/qa/unit/lockfiles/data/testMSOLockFileLongUserName.docx");
+ OUString aTestODT = generateTestURL("testMSOLockFileLongUserName.docx");
// Set user name
SvtUserOptions aUserOpt;
@@ -667,8 +649,7 @@ void LockfileTest::testMSOLockFileLongUserName()
void LockfileTest::testMSOLockFileUnicodeUsername()
{
// Test the lockfile generated for the specified ODT document
- OUString aTestODT = m_directories.getURLFromSrc(
- "/svl/qa/unit/lockfiles/data/testMSOLockFileUnicodeUsername.docx");
+ OUString aTestODT = generateTestURL("testMSOLockFileUnicodeUsername.docx");
// Set user name
SvtUserOptions aUserOpt;
@@ -694,8 +675,7 @@ void LockfileTest::testMSOLockFileUnicodeUsername()
void LockfileTest::testMSOLockFileOverwrite()
{
- OUString aTestODT
- = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testMSOLockFileOverwrite.docx");
+ OUString aTestODT = generateTestURL("testMSOLockFileOverwrite.docx");
// Set user name
SvtUserOptions aUserOpt;
@@ -725,7 +705,7 @@ void LockfileTest::testMSOLockFileOverwrite()
}
CPPUNIT_TEST_SUITE_REGISTRATION(LockfileTest);
-}
+} // namespace
CPPUNIT_PLUGIN_IMPLEMENT();
commit c9dcc2172727cd75f512409c39eef460d44396dd
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Tue Mar 26 16:12:49 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:21 2019 +0200
MSO lockfiles: Deduplicate MSO lock file reading code
The removed code was extracted to MSODocumentLockFile class
so use that class here too.
Use openStreamNoLock() for reading MSO lockfiles, because otherwise
we can not read lock files written by MSO.
Change-Id: Ib31cb9f3783d0b0ce784f900821047b9d32156f2
Reviewed-on: https://gerrit.libreoffice.org/69759
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit ad47e9b1c0d3f1720665b2786090e8c0927b5b45)
diff --git a/include/svl/documentlockfile.hxx b/include/svl/documentlockfile.hxx
index 87334e4b73e7..79bb087c8362 100644
--- a/include/svl/documentlockfile.hxx
+++ b/include/svl/documentlockfile.hxx
@@ -50,7 +50,7 @@ public:
protected:
virtual void WriteEntryToStream( const LockFileEntry& aEntry, const css::uno::Reference< css::io::XOutputStream >& xStream ) = 0;
- css::uno::Reference< css::io::XInputStream > OpenStream();
+ virtual css::uno::Reference< css::io::XInputStream > OpenStream();
};
/// Class implementing reading and writing LO lockfiles.
diff --git a/include/svl/msodocumentlockfile.hxx b/include/svl/msodocumentlockfile.hxx
index 2c438f0178cb..5fa6fcbf10bf 100644
--- a/include/svl/msodocumentlockfile.hxx
+++ b/include/svl/msodocumentlockfile.hxx
@@ -64,6 +64,8 @@ protected:
WriteEntryToStream(const LockFileEntry& aEntry,
const css::uno::Reference<css::io::XOutputStream>& xStream) override;
+ virtual css::uno::Reference<css::io::XInputStream> OpenStream() override;
+
public:
MSODocumentLockFile(const OUString& aOrigURL);
virtual ~MSODocumentLockFile() override;
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index dbdd98c294fb..a06ca65c65b9 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -893,84 +893,22 @@ void SfxMedium::SetEncryptionDataToStorage_Impl()
namespace
{
-OUString tryMSOwnerFile(const INetURLObject& aLockfileURL)
+
+OUString tryMSOwnerFiles(const OUString& sDocURL)
{
+ svt::MSODocumentLockFile aMSOLockFile(sDocURL);
+ LockFileEntry aData;
try
{
- static osl::Mutex aMutex;
- osl::MutexGuard aGuard(aMutex);
- css::uno::Reference<css::ucb::XCommandEnvironment> xEnv;
- ucbhelper::Content aSourceContent(
- aLockfileURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), xEnv,
- comphelper::getProcessComponentContext());
-
- // Excel creates Owner Files with FILE_FLAG_DELETE_ON_CLOSE, so we need to open it with
- // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE share mode
- css::uno::Reference<css::io::XInputStream> xStream = aSourceContent.openStreamNoLock();
- if (!xStream)
- return OUString();
-
- const sal_Int32 nBufLen = 256;
- css::uno::Sequence<sal_Int8> aBuf(nBufLen);
- const sal_Int32 nRead = xStream->readBytes(aBuf, nBufLen);
- xStream->closeInput();
- if (nRead >= 162)
- {
- // Reverse engineering of MS Office Owner Files format (MS Office 2016 tested).
- // It starts with a single byte with name length, after which characters of username go
- // in current Windows 8-bit codepage.
- // For Word lockfiles, the name is followed by zero bytes up to position 54.
- // For PowerPoint lockfiles, the name is followed by a single zero byte, and then 0x20
- // bytes up to position 55.
- // For Excel lockfiles, the name is followed by 0x20 bytes up to position 55.
- // At those positions in each type of lockfile, a name length 2-byte word goes, followed
- // by UTF-16-LE-encoded copy of username. Spaces or some garbage follow up to the end of
- // the lockfile (total 162 bytes for Word, 165 bytes for Excel/PowerPoint).
- // Apparently MS Office does not allow username to be longer than 52 characters (trying
- // to enter more in its options dialog results in error messages stating this limit).
- const int nACPLen = aBuf[0];
- if (nACPLen > 0 && nACPLen <= 52) // skip wrong format
- {
- const sal_Int8* pBuf = aBuf.getConstArray() + 54;
- int nUTF16Len = *pBuf; // try Word position
- // If UTF-16 length is 0x20, then ACP length is also less than maximal, which means
- // that in Word lockfile case, at least two preceeding bytes would be zero. Both
- // Excel and PowerPoint lockfiles would have at least one of those bytes non-zero.
- if (nUTF16Len == 0x20 && (*(pBuf - 1) != 0 || *(pBuf - 2) != 0))
- nUTF16Len = *++pBuf; // use Excel/PowerPoint position
-
- if (nUTF16Len > 0 && nUTF16Len <= 52) // skip wrong format
- return OUString(reinterpret_cast<const sal_Unicode*>(pBuf + 2), nUTF16Len);
- }
- }
+ aData = aMSOLockFile.GetLockData();
}
- catch (...) {} // we don't ever need to care about any exceptions here
-
- return OUString();
-}
-
-OUString tryMSOwnerFiles(const OUString& sDocURL)
-{
- INetURLObject aURL(sDocURL);
- if (aURL.HasError())
- return OUString();
- const OUString sFileName = aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
- if (sFileName.isEmpty())
- return OUString();
- const OUString sFileExt = aURL.GetFileExtension();
- const sal_Int32 nFileNameLen
- = sFileName.getLength() - sFileExt.getLength() - (sFileExt.isEmpty() ? 0 : 1);
- // Word, Excel, PowerPoint all prepend the filename with "~$".
- aURL.SetName("~$" + sFileName, INetURLObject::EncodeMechanism::All);
- OUString sUserData = tryMSOwnerFile(aURL);
- // Additionally, Word strips first chars of the filename: 1 for length 7, 2 for length >=8.
- if (sUserData.isEmpty() && nFileNameLen > 6)
+ catch( const uno::Exception& )
{
- aURL.SetName("~$" + sFileName.copy((nFileNameLen == 7) ? 1 : 2),
- INetURLObject::EncodeMechanism::All);
- sUserData = tryMSOwnerFile(aURL);
+ return OUString();
}
+ OUString sUserData = aData[LockFileComponent::OOOUSERNAME];
+
if (!sUserData.isEmpty())
sUserData += " (MS Office)"; // Mention the used office suite
diff --git a/svl/source/misc/msodocumentlockfile.cxx b/svl/source/misc/msodocumentlockfile.cxx
index e1afd70ef2e8..0309f86bc41e 100644
--- a/svl/source/misc/msodocumentlockfile.cxx
+++ b/svl/source/misc/msodocumentlockfile.cxx
@@ -11,10 +11,13 @@
#include <rtl/ustring.hxx>
#include <sal/log.hxx>
#include <algorithm>
+#include <ucbhelper/content.hxx>
+#include <comphelper/processfactory.hxx>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
namespace svt
{
@@ -179,6 +182,17 @@ void MSODocumentLockFile::WriteEntryToStream(
xOutput->writeBytes(aData);
}
+css::uno::Reference<css::io::XInputStream> MSODocumentLockFile::OpenStream()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ css::uno::Reference<css::ucb::XCommandEnvironment> xEnv;
+ ::ucbhelper::Content aSourceContent(GetURL(), xEnv, comphelper::getProcessComponentContext());
+
+ // the file can be opened readonly, no locking will be done
+ return aSourceContent.openStreamNoLock();
+}
+
LockFileEntry MSODocumentLockFile::GetLockData()
{
::osl::MutexGuard aGuard(m_aMutex);
commit dac99f6818e6e68198896e93835760b82df2703e
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Thu Jun 20 13:40:58 2019 +0200
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:21 2019 +0200
Generate MSO lock files when the related MSO compat. option is set
Added a new compatibility option to the Tools -> Load / Save ->
Microsoft.
When this option is set on the UI or or set in the configuration files
LO generates lock files for MSO supported file formats, similar to
the lock files MSO generates itself.
Reviewed-on: https://gerrit.libreoffice.org/69678
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit 41dc917b9b55b8c0c4307ffc58a1fb7257df2b69)
Change-Id: I2f882723841162add01be9d3f7285a5162a60331
diff --git a/cui/source/options/optfltr.cxx b/cui/source/options/optfltr.cxx
index 3d8b2fa04c52..ec3da63d7f5a 100644
--- a/cui/source/options/optfltr.cxx
+++ b/cui/source/options/optfltr.cxx
@@ -154,6 +154,7 @@ OfaMSFilterTabPage2::OfaMSFilterTabPage2( vcl::Window* pParent, const SfxItemSet
get( aHighlightingRB, "highlighting");
get( aShadingRB, "shading" );
+ get( aMSOLockFileCB, "mso_lockfile");
Size aControlSize(248, 55);
aControlSize = LogicToPixel(aControlSize, MapMode(MapUnit::MapAppFont));
@@ -184,6 +185,7 @@ void OfaMSFilterTabPage2::dispose()
m_pCheckLBContainer.clear();
aHighlightingRB.clear();
aShadingRB.clear();
+ aMSOLockFileCB.clear();
SfxTabPage::dispose();
}
@@ -253,6 +255,11 @@ bool OfaMSFilterTabPage2::FillItemSet( SfxItemSet* )
rOpt.SetCharBackground2Shading();
}
+ if( aMSOLockFileCB->IsValueChangedFromSaved() )
+ {
+ rOpt.EnableMSOLockFileCreation(aMSOLockFileCB->IsChecked());
+ }
+
return true;
}
@@ -319,6 +326,9 @@ void OfaMSFilterTabPage2::Reset( const SfxItemSet* )
aShadingRB->Check();
aHighlightingRB->SaveValue();
+
+ aMSOLockFileCB->Check(rOpt.IsMSOLockFileCreationIsEnabled());
+ aMSOLockFileCB->SaveValue();
}
void OfaMSFilterTabPage2::InsertEntry( const OUString& _rTxt, sal_IntPtr _nType )
diff --git a/cui/source/options/optfltr.hxx b/cui/source/options/optfltr.hxx
index 9782fd773ee5..91f393d6b893 100644
--- a/cui/source/options/optfltr.hxx
+++ b/cui/source/options/optfltr.hxx
@@ -85,6 +85,7 @@ class OfaMSFilterTabPage2 : public SfxTabPage
VclPtr<RadioButton> aHighlightingRB;
VclPtr<RadioButton> aShadingRB;
+ VclPtr<CheckBox> aMSOLockFileCB;
virtual ~OfaMSFilterTabPage2() override;
virtual void dispose() override;
diff --git a/cui/uiconfig/ui/optfltrembedpage.ui b/cui/uiconfig/ui/optfltrembedpage.ui
index 0e65b6cdce69..df931247be30 100644
--- a/cui/uiconfig/ui/optfltrembedpage.ui
+++ b/cui/uiconfig/ui/optfltrembedpage.ui
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.4 -->
<interface domain="cui">
<requires lib="gtk+" version="3.18"/>
<requires lib="LibreOffice" version="1.0"/>
@@ -48,8 +49,8 @@
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="xalign">0</property>
<property name="label" translatable="yes" context="optfltrembedpage|label2">[L]: Load and convert the object</property>
+ <property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
@@ -61,8 +62,8 @@
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="xalign">0</property>
<property name="label" translatable="yes" context="optfltrembedpage|label3">[S]: Convert and save the object</property>
+ <property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
@@ -88,8 +89,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -184,8 +183,60 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkCheckButton" id="mso_lockfile">
+ <property name="label" translatable="yes" context="optfltrembedpage|mso_lockfile">Create MSO lock file</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="optfltrembedpage|label5">Lock files</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
</packing>
</child>
</object>
diff --git a/include/svl/lockfilecommon.hxx b/include/svl/lockfilecommon.hxx
index e99ed64d7f36..97210d010279 100644
--- a/include/svl/lockfilecommon.hxx
+++ b/include/svl/lockfilecommon.hxx
@@ -68,7 +68,7 @@ public:
static OUString GetCurrentLocalTime();
static LockFileEntry GenerateOwnEntry();
- INetURLObject ResolveLinks( const INetURLObject& aDocURL ) const;
+ static INetURLObject ResolveLinks( const INetURLObject& aDocURL );
};
}
diff --git a/include/svl/msodocumentlockfile.hxx b/include/svl/msodocumentlockfile.hxx
index 75f03ff16d4b..2c438f0178cb 100644
--- a/include/svl/msodocumentlockfile.hxx
+++ b/include/svl/msodocumentlockfile.hxx
@@ -55,9 +55,9 @@ class SVL_DLLPUBLIC MSODocumentLockFile : public GenDocumentLockFile
private:
OUString m_sOrigURL;
- bool isWordFormat(const OUString& aOrigURL) const;
- bool isExcelFormat(const OUString& aOrigURL) const;
- bool isPowerPointFormat(const OUString& aOrigURL) const;
+ static bool isWordFormat(const OUString& aOrigURL);
+ static bool isExcelFormat(const OUString& aOrigURL);
+ static bool isPowerPointFormat(const OUString& aOrigURL);
protected:
virtual void
@@ -74,6 +74,8 @@ public:
virtual LockFileEntry GetLockData() override;
virtual void RemoveFile() override;
+
+ static bool IsMSOSupportedFileFormat(const OUString& aURL);
};
} // namespace svt
diff --git a/include/unotools/fltrcfg.hxx b/include/unotools/fltrcfg.hxx
index ab0eb1364e81..bc5630cac444 100644
--- a/include/unotools/fltrcfg.hxx
+++ b/include/unotools/fltrcfg.hxx
@@ -91,6 +91,9 @@ public:
void SetCharBackground2Highlighting();
void SetCharBackground2Shading();
+ bool IsMSOLockFileCreationIsEnabled() const;
+ void EnableMSOLockFileCreation(bool bEnable);
+
static SvtFilterOptions& Get();
};
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index ecc913106447..b790dab22ba9 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -3820,6 +3820,14 @@
</info>
<value>true</value>
</prop>
+ <prop oor:name="CreateMSOLockFiles" oor:type="xs:boolean" oor:nillable="false">
+ <info>
+ <desc>Specifies if LO should create MSO lock files next to the LO lock files
+ when openning a file. This makes MSO to be able to read the user name from
+ the lock file and show it for the user.</desc>
+ </info>
+ <value>false</value>
+ </prop>
</group>
<group oor:name="Export">
<info>
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index 14723e934dc7..dbdd98c294fb 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -116,6 +116,7 @@
#include <sot/storage.hxx>
#include <unotools/saveopt.hxx>
#include <svl/documentlockfile.hxx>
+#include <svl/msodocumentlockfile.hxx>
#include <com/sun/star/document/DocumentRevisionListPersistence.hpp>
#include <helper.hxx>
@@ -130,7 +131,10 @@
#include <openflag.hxx>
#include <officecfg/Office/Common.hxx>
#include <comphelper/propertysequence.hxx>
-
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/fltrcfg.hxx>
#include <com/sun/star/io/WrongFormatException.hpp>
#include <memory>
@@ -255,6 +259,7 @@ public:
bool m_bSalvageMode:1;
bool m_bVersionsAlreadyLoaded:1;
bool m_bLocked:1;
+ bool m_bMSOLockFileCreated : 1;
bool m_bDisableUnlockWebDAV:1;
bool m_bGotDateTime:1;
bool m_bRemoveBackup:1;
@@ -335,6 +340,7 @@ SfxMedium_Impl::SfxMedium_Impl() :
m_bSalvageMode( false ),
m_bVersionsAlreadyLoaded( false ),
m_bLocked( false ),
+ m_bMSOLockFileCreated( false ),
m_bDisableUnlockWebDAV( false ),
m_bGotDateTime( false ),
m_bRemoveBackup( false ),
@@ -1400,6 +1406,15 @@ SfxMedium::LockFileResult SfxMedium::LockOrigFileOnDemand( bool bLoading, bool b
try
{
::svt::DocumentLockFile aLockFile( pImpl->m_aLogicName );
+
+ std::unique_ptr<svt::MSODocumentLockFile> pMSOLockFile;
+ const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
+ if (rOpt.IsMSOLockFileCreationIsEnabled() && svt::MSODocumentLockFile::IsMSOSupportedFileFormat(pImpl->m_aLogicName))
+ {
+ pMSOLockFile.reset(new svt::MSODocumentLockFile(pImpl->m_aLogicName));
+ pImpl->m_bMSOLockFileCreated = true;
+ }
+
bool bIoErr = false;
if (!bHandleSysLocked)
@@ -1407,6 +1422,8 @@ SfxMedium::LockFileResult SfxMedium::LockOrigFileOnDemand( bool bLoading, bool b
try
{
bResult = aLockFile.CreateOwnLockFile();
+ if(pMSOLockFile)
+ bResult &= pMSOLockFile->CreateOwnLockFile();
}
catch (const uno::Exception&)
{
@@ -1431,6 +1448,9 @@ SfxMedium::LockFileResult SfxMedium::LockOrigFileOnDemand( bool bLoading, bool b
bResult = true;
// take the ownership over the lock file
aLockFile.OverwriteOwnLockFile();
+
+ if(pMSOLockFile)
+ pMSOLockFile->OverwriteOwnLockFile();
}
}
@@ -1486,6 +1506,9 @@ SfxMedium::LockFileResult SfxMedium::LockOrigFileOnDemand( bool bLoading, bool b
{
// take the ownership over the lock file
bResult = aLockFile.OverwriteOwnLockFile();
+
+ if(pMSOLockFile)
+ pMSOLockFile->OverwriteOwnLockFile();
}
else if (bLoading && !bHandleSysLocked)
eResult = LockFileResult::FailedLockFile;
@@ -3032,6 +3055,31 @@ void SfxMedium::UnlockFile( bool bReleaseLockStream )
}
catch( const uno::Exception& )
{}
+
+ if(pImpl->m_bMSOLockFileCreated)
+ {
+ ::svt::MSODocumentLockFile aMSOLockFile( pImpl->m_aLogicName );
+
+ try
+ {
+ pImpl->m_bLocked = false;
+ // TODO/LATER: A warning could be shown in case the file is not the own one
+ aMSOLockFile.RemoveFile();
+ }
+ catch( const io::WrongFormatException& )
+ {
+ try
+ {
+ // erase the empty or corrupt file
+ aMSOLockFile.RemoveFileDirectly();
+ }
+ catch( const uno::Exception& )
+ {}
+ }
+ catch( const uno::Exception& )
+ {}
+ pImpl->m_bMSOLockFileCreated = false;
+ }
}
#endif
}
diff --git a/svl/qa/unit/lockfiles/test_lockfiles.cxx b/svl/qa/unit/lockfiles/test_lockfiles.cxx
index 8083c143f461..5f23240f387c 100644
--- a/svl/qa/unit/lockfiles/test_lockfiles.cxx
+++ b/svl/qa/unit/lockfiles/test_lockfiles.cxx
@@ -88,7 +88,7 @@ OUString readLockFile(const OUString& aSource)
OUString GetLockFileName(const svt::GenDocumentLockFile& rLockFile)
{
- INetURLObject aDocURL = rLockFile.ResolveLinks(INetURLObject(rLockFile.GetURL()));
+ INetURLObject aDocURL = svt::LockFileCommon::ResolveLinks(INetURLObject(rLockFile.GetURL()));
return aDocURL.GetName();
}
diff --git a/svl/source/misc/lockfilecommon.cxx b/svl/source/misc/lockfilecommon.cxx
index 30b53745c620..f0a1db6864e0 100644
--- a/svl/source/misc/lockfilecommon.cxx
+++ b/svl/source/misc/lockfilecommon.cxx
@@ -94,7 +94,7 @@ OUString LockFileCommon::GenerateURL( const OUString& aOrigURL, const OUString&
}
-INetURLObject LockFileCommon::ResolveLinks( const INetURLObject& aDocURL ) const
+INetURLObject LockFileCommon::ResolveLinks( const INetURLObject& aDocURL )
{
if ( aDocURL.HasError() )
throw lang::IllegalArgumentException();
diff --git a/svl/source/misc/msodocumentlockfile.cxx b/svl/source/misc/msodocumentlockfile.cxx
index 938b36d5cd26..e1afd70ef2e8 100644
--- a/svl/source/misc/msodocumentlockfile.cxx
+++ b/svl/source/misc/msodocumentlockfile.cxx
@@ -18,9 +18,9 @@
namespace svt
{
-bool MSODocumentLockFile::isWordFormat(const OUString& aOrigURL) const
+bool MSODocumentLockFile::isWordFormat(const OUString& aOrigURL)
{
- INetURLObject aDocURL = ResolveLinks(INetURLObject(aOrigURL));
+ INetURLObject aDocURL = LockFileCommon::ResolveLinks(INetURLObject(aOrigURL));
return aDocURL.GetFileExtension().compareToIgnoreAsciiCase("DOC") == 0
|| aDocURL.GetFileExtension().compareToIgnoreAsciiCase("DOCX") == 0
@@ -28,18 +28,18 @@ bool MSODocumentLockFile::isWordFormat(const OUString& aOrigURL) const
|| aDocURL.GetFileExtension().compareToIgnoreAsciiCase("ODT") == 0;
}
-bool MSODocumentLockFile::isExcelFormat(const OUString& aOrigURL) const
+bool MSODocumentLockFile::isExcelFormat(const OUString& aOrigURL)
{
- INetURLObject aDocURL = ResolveLinks(INetURLObject(aOrigURL));
+ INetURLObject aDocURL = LockFileCommon::ResolveLinks(INetURLObject(aOrigURL));
return //aDocURL.GetFileExtension().compareToIgnoreAsciiCase("XLS") || // MSO does not create lockfile for XLS
aDocURL.GetFileExtension().compareToIgnoreAsciiCase("XLSX") == 0
|| aDocURL.GetFileExtension().compareToIgnoreAsciiCase("ODS") == 0;
}
-bool MSODocumentLockFile::isPowerPointFormat(const OUString& aOrigURL) const
+bool MSODocumentLockFile::isPowerPointFormat(const OUString& aOrigURL)
{
- INetURLObject aDocURL = ResolveLinks(INetURLObject(aOrigURL));
+ INetURLObject aDocURL = LockFileCommon::ResolveLinks(INetURLObject(aOrigURL));
return aDocURL.GetFileExtension().compareToIgnoreAsciiCase("PPTX") == 0
|| aDocURL.GetFileExtension().compareToIgnoreAsciiCase("PPT") == 0
@@ -56,7 +56,7 @@ MSODocumentLockFile::~MSODocumentLockFile() {}
OUString MSODocumentLockFile::GenerateURL(const OUString& aOrigURL, const OUString& aPrefix)
{
- INetURLObject aDocURL = ResolveLinks(INetURLObject(aOrigURL));
+ INetURLObject aDocURL = LockFileCommon::ResolveLinks(INetURLObject(aOrigURL));
OUString aURL = aDocURL.GetPartBeforeLastName();
aURL += aPrefix;
@@ -239,6 +239,11 @@ void MSODocumentLockFile::RemoveFile()
RemoveFileDirectly();
}
+bool MSODocumentLockFile::IsMSOSupportedFileFormat(const OUString& aURL)
+{
+ return isWordFormat(aURL) || isExcelFormat(aURL) || isPowerPointFormat(aURL);
+}
+
} // namespace svt
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/unotools/source/config/fltrcfg.cxx b/unotools/source/config/fltrcfg.cxx
index 32a61fdae8a1..605239d62ced 100644
--- a/unotools/source/config/fltrcfg.cxx
+++ b/unotools/source/config/fltrcfg.cxx
@@ -25,6 +25,7 @@
#include <tools/debug.hxx>
#include <tools/solar.h>
#include <osl/diagnose.h>
+#include <sal/log.hxx>
#include <com/sun/star/uno/Sequence.hxx>
@@ -54,10 +55,11 @@ enum class ConfigFlags {
UseEnhancedFields = 0x0100000,
WordWbctbl = 0x0200000,
SmartArtShapeLoad = 0x0400000,
- CharBackgroundToHighlighting = 0x8000000
+ CharBackgroundToHighlighting = 0x8000000,
+ CreateMSOLockFiles = 0x2000000
};
namespace o3tl {
- template<> struct typed_flags<ConfigFlags> : is_typed_flags<ConfigFlags, 0x87fff3f> {};
+ template<> struct typed_flags<ConfigFlags> : is_typed_flags<ConfigFlags, 0xf7fff3f> {};
}
class SvtAppFilterOptions_Impl : public utl::ConfigItem
@@ -246,7 +248,8 @@ struct SvtFilterOptions_Impl
ConfigFlags::ImpressSave |
ConfigFlags::UseEnhancedFields |
ConfigFlags::SmartArtShapeLoad |
- ConfigFlags::CharBackgroundToHighlighting;
+ ConfigFlags::CharBackgroundToHighlighting|
+ ConfigFlags::CreateMSOLockFiles;
Load();
}
@@ -306,7 +309,7 @@ const Sequence<OUString>& GetPropertyNames()
static Sequence<OUString> aNames;
if(!aNames.getLength())
{
- int nCount = 14;
+ int nCount = 15;
aNames.realloc(nCount);
static const char* aPropNames[] =
{
@@ -323,7 +326,8 @@ const Sequence<OUString>& GetPropertyNames()
"Export/EnableWordPreview", // 10
"Import/ImportWWFieldsAsEnhancedFields", // 11
"Import/SmartArtToShapes", // 12
- "Export/CharBackgroundToHighlighting" // 13
+ "Export/CharBackgroundToHighlighting", // 13
+ "Import/CreateMSOLockFiles" // 14
};
OUString* pNames = aNames.getArray();
for(int i = 0; i < nCount; i++)
@@ -365,6 +369,7 @@ static ConfigFlags lcl_GetFlag(sal_Int32 nProp)
case 11: nFlag = ConfigFlags::UseEnhancedFields; break;
case 12: nFlag = ConfigFlags::SmartArtShapeLoad; break;
case 13: nFlag = ConfigFlags::CharBackgroundToHighlighting; break;
+ case 14: nFlag = ConfigFlags::CreateMSOLockFiles; break;
default: OSL_FAIL("illegal value");
}
@@ -632,7 +637,6 @@ bool SvtFilterOptions::IsEnableWordPreview() const
return pImpl->IsFlag( ConfigFlags::EnableWordPreview );
}
-
bool SvtFilterOptions::IsCharBackground2Highlighting() const
{
return pImpl->IsFlag( ConfigFlags::CharBackgroundToHighlighting );
@@ -655,4 +659,15 @@ void SvtFilterOptions::SetCharBackground2Shading()
SetModified();
}
+bool SvtFilterOptions::IsMSOLockFileCreationIsEnabled() const
+{
+ return pImpl->IsFlag( ConfigFlags::CreateMSOLockFiles );
+}
+
+void SvtFilterOptions::EnableMSOLockFileCreation(bool bEnable)
+{
+ pImpl->SetFlag( ConfigFlags::CreateMSOLockFiles, bEnable );
+ SetModified();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit f5946cd499f7d7de40b03f453f5b1c52e31a29fc
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
AuthorDate: Sat Mar 23 15:53:27 2019 +0100
Commit: Tamás Zolnai <tamas.zolnai at collabora.com>
CommitDate: Thu Jun 20 14:23:20 2019 +0200
Introduce new lockfile handler for MSO like lockfiles
* Implement writing of MSO lockfiles
* Grab the already implemented parsing code (tryMSOwnerFile method)
and put it together into one class
* Add tests about the generated URL for lockfiles and the lockfile content
* MSO lockfiles are not written yet by LO, next step is to integrate
this code into the locking mechanism.
Reviewed-on: https://gerrit.libreoffice.org/69582
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit 5db1e20b8b0942dac2d50f3cd34532bb61147020)
Change-Id: I3b0ed1975cd57dfd006d4e1890b23c307890de5c
Reviewed-on: https://gerrit.libreoffice.org/69842
Reviewed-by: Andras Timar <andras.timar at collabora.com>
Tested-by: Andras Timar <andras.timar at collabora.com>
diff --git a/include/svl/documentlockfile.hxx b/include/svl/documentlockfile.hxx
index 25531dc3332e..87334e4b73e7 100644
--- a/include/svl/documentlockfile.hxx
+++ b/include/svl/documentlockfile.hxx
@@ -29,28 +29,41 @@ namespace com { namespace sun { namespace star { namespace io { class XOutputStr
namespace svt {
-class SVL_DLLPUBLIC DocumentLockFile : public LockFileCommon
+/// Generalized class for LO and MSO lockfile handling.
+class SVL_DLLPUBLIC GenDocumentLockFile : public LockFileCommon
{
- // the workaround for automated testing!
- static bool m_bAllowInteraction;
-
- css::uno::Reference< css::io::XInputStream > OpenStream();
-
- void WriteEntryToStream( const LockFileEntry& aEntry, const css::uno::Reference< css::io::XOutputStream >& xStream );
-
public:
- DocumentLockFile( const OUString& aOrigURL );
- ~DocumentLockFile();
+ /// Specify the lockfile URL directly
+ GenDocumentLockFile( const OUString& aURL );
+ /// Let the object generate and own URL based on the original file's URL and a prefix
+ GenDocumentLockFile( const OUString& aOrigURL, const OUString& aPrefix );
+ virtual ~GenDocumentLockFile() override;
bool CreateOwnLockFile();
- LockFileEntry GetLockData();
bool OverwriteOwnLockFile();
/// Delete the Lockfile, if current user is the owner
- void RemoveFile();
+ virtual void RemoveFile();
/// Only delete lockfile, disregarding ownership
void RemoveFileDirectly();
- static bool IsInteractionAllowed() { return m_bAllowInteraction; }
+ virtual LockFileEntry GetLockData() = 0;
+
+protected:
+ virtual void WriteEntryToStream( const LockFileEntry& aEntry, const css::uno::Reference< css::io::XOutputStream >& xStream ) = 0;
+ css::uno::Reference< css::io::XInputStream > OpenStream();
+};
+
+/// Class implementing reading and writing LO lockfiles.
+class SVL_DLLPUBLIC DocumentLockFile : public GenDocumentLockFile
+{
+protected:
+ virtual void WriteEntryToStream( const LockFileEntry& aEntry, const css::uno::Reference< css::io::XOutputStream >& xStream ) override;
+
+public:
+ DocumentLockFile( const OUString& aOrigURL );
+ virtual ~DocumentLockFile() override;
+
+ virtual LockFileEntry GetLockData() override;
};
}
diff --git a/include/svl/lockfilecommon.hxx b/include/svl/lockfilecommon.hxx
index 4c5c6b5fe2e7..e99ed64d7f36 100644
--- a/include/svl/lockfilecommon.hxx
+++ b/include/svl/lockfilecommon.hxx
@@ -38,18 +38,27 @@ typedef o3tl::enumarray<LockFileComponent,OUString> LockFileEntry;
namespace svt {
-// This is a general implementation that is used in document lock file implementation and in sharing control file implementation
+/// This is a general implementation that is used in document lock file implementation and in sharing control file implementation
class SVL_DLLPUBLIC LockFileCommon
{
-protected:
- ::osl::Mutex m_aMutex;
+private:
OUString m_aURL;
- INetURLObject ResolveLinks( const INetURLObject& aDocURL ) const;
+protected:
+ ::osl::Mutex m_aMutex;
public:
+ /// Specify the lockfile URL directly
+ LockFileCommon( const OUString& aURL );
+ /// Let the object generate and own URL based on the original file's URL and a prefix
LockFileCommon( const OUString& aOrigURL, const OUString& aPrefix );
- ~LockFileCommon();
+ virtual ~LockFileCommon();
+
+ const OUString& GetURL() const;
+ void SetURL(const OUString& aURL);
+
+ /// This method generates the URL of the lock file based on the document URL and the specified prefix.
+ virtual OUString GenerateURL( const OUString& aOrigURL, const OUString& aPrefix );
static void ParseList( const css::uno::Sequence< sal_Int8 >& aBuffer, std::vector< LockFileEntry > &rOutput );
static LockFileEntry ParseEntry( const css::uno::Sequence< sal_Int8 >& aBuffer, sal_Int32& o_nCurPos );
@@ -58,6 +67,8 @@ public:
static OUString GetOOOUserName();
static OUString GetCurrentLocalTime();
static LockFileEntry GenerateOwnEntry();
+
+ INetURLObject ResolveLinks( const INetURLObject& aDocURL ) const;
};
}
diff --git a/include/svl/msodocumentlockfile.hxx b/include/svl/msodocumentlockfile.hxx
new file mode 100644
index 000000000000..75f03ff16d4b
--- /dev/null
+++ b/include/svl/msodocumentlockfile.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; 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/.
+ */
+
+#ifndef INCLUDED_SVL_MSODOCUMENTLOCKFILE_HXX
+#define INCLUDED_SVL_MSODOCUMENTLOCKFILE_HXX
+
+#include <svl/svldllapi.h>
+#include <svl/lockfilecommon.hxx>
+#include <svl/documentlockfile.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+
+namespace com
+{
+namespace sun
+{
+namespace star
+{
+namespace io
+{
+class XInputStream;
+}
+} // namespace star
+} // namespace sun
+} // namespace com
+namespace com
+{
+namespace sun
+{
+namespace star
+{
+namespace io
+{
+class XOutputStream;
+}
+} // namespace star
+} // namespace sun
+} // namespace com
+
+#define MSO_WORD_LOCKFILE_SIZE 162
+#define MSO_EXCEL_AND_POWERPOINT_LOCKFILE_SIZE 165
+#define MSO_USERNAME_MAX_LENGTH 52
+
+namespace svt
+{
+/// Class implementing reading and writing MSO lockfiles.
+class SVL_DLLPUBLIC MSODocumentLockFile : public GenDocumentLockFile
+{
+private:
+ OUString m_sOrigURL;
+
+ bool isWordFormat(const OUString& aOrigURL) const;
+ bool isExcelFormat(const OUString& aOrigURL) const;
+ bool isPowerPointFormat(const OUString& aOrigURL) const;
+
+protected:
+ virtual void
+ WriteEntryToStream(const LockFileEntry& aEntry,
+ const css::uno::Reference<css::io::XOutputStream>& xStream) override;
+
+public:
+ MSODocumentLockFile(const OUString& aOrigURL);
+ virtual ~MSODocumentLockFile() override;
+
+ /// Need to generate different lock file name for MSO.
+ virtual OUString GenerateURL(const OUString& aOrigURL, const OUString& aPrefix) override;
+
+ virtual LockFileEntry GetLockData() override;
+
+ virtual void RemoveFile() override;
+};
+} // namespace svt
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/svl/sharecontrolfile.hxx b/include/svl/sharecontrolfile.hxx
index 8dfa91669ddc..dd52d48da8f7 100644
--- a/include/svl/sharecontrolfile.hxx
+++ b/include/svl/sharecontrolfile.hxx
@@ -53,7 +53,7 @@ public:
// The constructor will throw exception in case the stream can not be opened
ShareControlFile( const OUString& aOrigURL );
- ~ShareControlFile();
+ virtual ~ShareControlFile() override;
std::vector< LockFileEntry > GetUsersData();
void SetUsersDataAndStore( const std::vector< LockFileEntry >& aUserNames );
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index 08848fd6808d..14723e934dc7 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -993,7 +993,7 @@ SfxMedium::ShowLockResult SfxMedium::ShowLockedDocumentDialog(const OUString& aD
// show the interaction regarding the document opening
uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
- if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler.is() && ( bIsLoading || !bHandleSysLocked || bOwnLock ) )
+ if ( xHandler.is() && ( bIsLoading || !bHandleSysLocked || bOwnLock ) )
{
OUString aDocumentURL
= GetURLObject().GetLastName(INetURLObject::DecodeMechanism::WithCharset);
diff --git a/svl/CppunitTest_svl_lockfiles.mk b/svl/CppunitTest_svl_lockfiles.mk
new file mode 100644
index 000000000000..c93e78b45b8d
--- /dev/null
+++ b/svl/CppunitTest_svl_lockfiles.mk
@@ -0,0 +1,52 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,svl_lockfiles))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,svl_lockfiles))
+
+$(eval $(call gb_CppunitTest_use_api,svl_lockfiles,\
+ udkapi \
+ offapi \
+ oovbaapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,svl_lockfiles))
+
+$(eval $(call gb_CppunitTest_use_vcl,svl_lockfiles))
+
+
+$(eval $(call gb_CppunitTest_add_exception_objects,svl_lockfiles, \
+ svl/qa/unit/lockfiles/test_lockfiles \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,svl_lockfiles, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ tl \
+ sal \
+ svl \
+ svt \
+ sw \
+ test \
+ unotest \
+ utl \
+ vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_rdb,svl_lockfiles,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,svl_lockfiles,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,svl_lockfiles))
+
+# vim: set noet sw=4 ts=4:
diff --git a/svl/Library_svl.mk b/svl/Library_svl.mk
index 2103a1483a45..4dad7be2a929 100644
--- a/svl/Library_svl.mk
+++ b/svl/Library_svl.mk
@@ -163,7 +163,8 @@ $(eval $(call gb_Library_add_exception_objects,svl,\
svl/source/misc/PasswordHelper \
svl/source/misc/adrparse \
$(if $(filter DESKTOP,$(BUILD_TYPE)),\
- svl/source/misc/documentlockfile) \
+ svl/source/misc/documentlockfile \
+ svl/source/misc/msodocumentlockfile) \
svl/source/misc/filenotation \
svl/source/misc/fstathelper \
svl/source/misc/getstringresource \
diff --git a/svl/Module_svl.mk b/svl/Module_svl.mk
index d14e184b65a9..2569edb05b64 100644
--- a/svl/Module_svl.mk
+++ b/svl/Module_svl.mk
@@ -34,6 +34,7 @@ $(eval $(call gb_Module_add_check_targets,svl,\
CppunitTest_svl_itempool \
CppunitTest_svl_items \
CppunitTest_svl_lngmisc \
+ CppunitTest_svl_lockfiles \
CppunitTest_svl_notify \
CppunitTest_svl_qa_cppunit \
CppunitTest_svl_urihelper \
diff --git a/svl/qa/unit/lockfiles/test_lockfiles.cxx b/svl/qa/unit/lockfiles/test_lockfiles.cxx
new file mode 100644
index 000000000000..8083c143f461
--- /dev/null
+++ b/svl/qa/unit/lockfiles/test_lockfiles.cxx
@@ -0,0 +1,732 @@
+/* -*- Mode: C++; 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/.
+ */
+
+#include <sal/config.h>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <test/bootstrapfixture.hxx>
+
+#include <unotest/directories.hxx>
+#include <svl/lockfilecommon.hxx>
+#include <svl/documentlockfile.hxx>
+#include <svl/msodocumentlockfile.hxx>
+#include <unotools/useroptions.hxx>
+#include <comphelper/sequence.hxx>
+#include <tools/stream.hxx>
+#include <rtl/strbuf.hxx>
+#include <osl/security.hxx>
+#include <osl/socket.hxx>
+#include <unotools/bootstrap.hxx>
+
+namespace
+{
+class LockfileTest : public test::BootstrapFixture
+{
+public:
+ void testLOLockFileURL();
+ void testLOLockFileContent();
+ void testLOLockFileRT();
+ void testLOLockFileUnicodeUsername();
+ void testLOLockFileOverwrite();
+ void testWordLockFileURL();
+ void testExcelLockFileURL();
+ void testPowerPointLockFileURL();
+ void testWordLockFileContent();
+ void testExcelLockFileContent();
+ void testPowerPointLockFileContent();
+ void testWordLockFileRT();
+ void testExcelLockFileRT();
+ void testPowerPointLockFileRT();
+ void testMSOLockFileLongUserName();
+ void testMSOLockFileUnicodeUsername();
+ void testMSOLockFileOverwrite();
+
+private:
+ CPPUNIT_TEST_SUITE(LockfileTest);
+ CPPUNIT_TEST(testLOLockFileURL);
+ CPPUNIT_TEST(testLOLockFileContent);
+ CPPUNIT_TEST(testLOLockFileRT);
+ CPPUNIT_TEST(testLOLockFileUnicodeUsername);
+ CPPUNIT_TEST(testLOLockFileOverwrite);
+ CPPUNIT_TEST(testWordLockFileURL);
+ CPPUNIT_TEST(testExcelLockFileURL);
+ CPPUNIT_TEST(testPowerPointLockFileURL);
+ CPPUNIT_TEST(testWordLockFileContent);
+ CPPUNIT_TEST(testExcelLockFileContent);
+ CPPUNIT_TEST(testPowerPointLockFileContent);
+ CPPUNIT_TEST(testWordLockFileRT);
+ CPPUNIT_TEST(testExcelLockFileRT);
+ CPPUNIT_TEST(testPowerPointLockFileRT);
+ CPPUNIT_TEST(testMSOLockFileLongUserName);
+ CPPUNIT_TEST(testMSOLockFileUnicodeUsername);
+ CPPUNIT_TEST(testMSOLockFileOverwrite);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+OUString readLockFile(const OUString& aSource)
+{
+ SvFileStream aFileStream(aSource, StreamMode::READ);
+ std::size_t nSize = aFileStream.remainingSize();
+ std::unique_ptr<sal_Int8[]> pBuffer(new sal_Int8[nSize]);
+ aFileStream.ReadBytes(pBuffer.get(), nSize);
+
+ css::uno::Sequence<sal_Int8> aData(pBuffer.get(), nSize);
+ OStringBuffer aResult;
+ for (sal_Int8 nByte : aData)
+ {
+ aResult.append(static_cast<sal_Char>(nByte));
+ }
+ return OStringToOUString(aResult.makeStringAndClear(), RTL_TEXTENCODING_UTF8);
+}
+
+OUString GetLockFileName(const svt::GenDocumentLockFile& rLockFile)
+{
+ INetURLObject aDocURL = rLockFile.ResolveLinks(INetURLObject(rLockFile.GetURL()));
+ return aDocURL.GetName();
+}
+
+void LockfileTest::testLOLockFileURL()
+{
+ // Test the generated file name for LibreOffice lock files
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileURL.odt");
+
+ svt::DocumentLockFile aLockFile(aTestODT);
+ CPPUNIT_ASSERT_EQUAL(OUString(".~lock.testLOLockFileURL.odt%23"), GetLockFileName(aLockFile));
+}
+
+void LockfileTest::testLOLockFileContent()
+{
+ // Test the lockfile generated for the specified ODT document
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileContent.odt");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and check the content
+ svt::DocumentLockFile aLockFile(aTestODT);
+ aLockFile.CreateOwnLockFile();
+ OUString sLockFileContent(readLockFile(aLockFile.GetURL()));
+ aLockFile.RemoveFileDirectly();
+
+ // User name
+ sal_Int32 nFirstChar = 0;
+ sal_Int32 nNextComma = sLockFileContent.indexOf(',', nFirstChar);
+ OUString sUserName;
+ sUserName += aUserOpt.GetFirstName() + " ";
+ sUserName += aUserOpt.GetLastName();
+ CPPUNIT_ASSERT_EQUAL(sUserName, sLockFileContent.copy(nFirstChar, nNextComma - nFirstChar));
+
+ // System user name
+ nFirstChar = nNextComma + 1;
+ nNextComma = sLockFileContent.indexOf(',', nFirstChar);
+ ::osl::Security aSecurity;
+ OUString sSysUserName;
+ aSecurity.getUserName(sSysUserName);
+ CPPUNIT_ASSERT_EQUAL(sSysUserName, sLockFileContent.copy(nFirstChar, nNextComma - nFirstChar));
+
+ // Local host
+ nFirstChar = nNextComma + 1;
+ nNextComma = sLockFileContent.indexOf(',', nFirstChar);
+ CPPUNIT_ASSERT_EQUAL(::osl::SocketAddr::getLocalHostname(),
+ sLockFileContent.copy(nFirstChar, nNextComma - nFirstChar));
+
+ // Skip date and time because it changes after the lock file was created
+ nFirstChar = nNextComma + 1;
+ nNextComma = sLockFileContent.indexOf(',', nFirstChar);
+
+ // user url
+ nFirstChar = nNextComma + 1;
+ OUString aUserInstDir;
+ ::utl::Bootstrap::locateUserInstallation(aUserInstDir);
+ CPPUNIT_ASSERT_EQUAL(
+ aUserInstDir,
+ sLockFileContent.copy(nFirstChar, sLockFileContent.getLength() - nFirstChar - 1));
+}
+
+void LockfileTest::testLOLockFileRT()
+{
+ // Test the lockfile generated for the specified ODT document
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileRT.odt");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and read it back
+ svt::DocumentLockFile aLockFile(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile.CreateOwnLockFile();
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+
+ // Check whether the lock file attributes are the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::SYSUSERNAME],
+ aRTEntry[LockFileComponent::SYSUSERNAME]);
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::LOCALHOST],
+ aRTEntry[LockFileComponent::LOCALHOST]);
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::USERURL],
+ aRTEntry[LockFileComponent::USERURL]);
+ // LockFileComponent::EDITTIME can change
+
+ aLockFile.RemoveFileDirectly();
+}
+
+void LockfileTest::testLOLockFileUnicodeUsername()
+{
+ // Test the lockfile generated for the specified ODT document
+ OUString aTestODT = m_directories.getURLFromSrc(
+ "/svl/qa/unit/lockfiles/data/testLOLockFileUnicodeUsername.odt");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ sal_Unicode vFirstName[] = { 2351, 2676, 3117, 5279 };
+ aUserOpt.SetToken(UserOptToken::FirstName, OUString(vFirstName, 4));
+ sal_Unicode vLastName[] = { 671, 1245, 1422, 1822 };
+ aUserOpt.SetToken(UserOptToken::LastName, OUString(vLastName, 4));
+
+ // Write the lock file and read it back
+ svt::DocumentLockFile aLockFile(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile.CreateOwnLockFile();
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+
+ // Check whether the lock file attributes are the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+ CPPUNIT_ASSERT_EQUAL(OUString(aUserOpt.GetFirstName() + " " + aUserOpt.GetLastName()),
+ aOrigEntry[LockFileComponent::OOOUSERNAME]);
+
+ aLockFile.RemoveFileDirectly();
+}
+
+void LockfileTest::testLOLockFileOverwrite()
+{
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testLOLockFileOverwrite.odt");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and read it back
+ svt::DocumentLockFile aLockFile(aTestODT);
+ aLockFile.CreateOwnLockFile();
+
+ // Change user name
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile2");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Overwrite lockfile
+ svt::DocumentLockFile aLockFile2(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile2.OverwriteOwnLockFile();
+
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+
+ // Check whether the lock file attributes are the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::SYSUSERNAME],
+ aRTEntry[LockFileComponent::SYSUSERNAME]);
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::LOCALHOST],
+ aRTEntry[LockFileComponent::LOCALHOST]);
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::USERURL],
+ aRTEntry[LockFileComponent::USERURL]);
+
+ aLockFile2.RemoveFileDirectly();
+}
+
+void LockfileTest::testWordLockFileURL()
+{
+ // Test the generated file name for Word lock files
+
+ // Word specific file format
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testWordLockFileURL.docx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$stWordLockFileURL.docx"), GetLockFileName(aLockFile));
+ }
+
+ // Eight character file name (cuts two characters)
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.docx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$345678.docx"), GetLockFileName(aLockFile));
+ }
+
+ // Seven character file name (cuts one character)
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1234567.docx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$234567.docx"), GetLockFileName(aLockFile));
+ }
+
+ // Six character file name (cuts no character)
+ {
+ OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/123456.docx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$123456.docx"), GetLockFileName(aLockFile));
+ }
+
+ // One character file name
+ {
+ OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1.docx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$1.docx"), GetLockFileName(aLockFile));
+ }
+
+ // Test for ODT format
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.odt");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$345678.odt"), GetLockFileName(aLockFile));
+ }
+
+ // Test for DOC format
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.doc");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$345678.doc"), GetLockFileName(aLockFile));
+ }
+
+ // Test for RTF format
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.rtf");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$345678.rtf"), GetLockFileName(aLockFile));
+ }
+}
+
+void LockfileTest::testExcelLockFileURL()
+{
+ // Test the generated file name for Excel lock files
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testExcelLockFileURL.xlsx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$testExcelLockFileURL.xlsx"), GetLockFileName(aLockFile));
+ }
+
+ // Eight character file name
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.xlsx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.xlsx"), GetLockFileName(aLockFile));
+ }
+
+ // One character file name
+ {
+ OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1.xlsx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$1.xlsx"), GetLockFileName(aLockFile));
+ }
+
+ // Test for ODS format
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.ods");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.ods"), GetLockFileName(aLockFile));
+ }
+}
+
+void LockfileTest::testPowerPointLockFileURL()
+{
+ // Test the generated file name for PowerPoint lock files
+ {
+ OUString aTestFile = m_directories.getURLFromSrc(
+ "/svl/qa/unit/lockfiles/data/testPowerPointLockFileURL.pptx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$testPowerPointLockFileURL.pptx"),
+ GetLockFileName(aLockFile));
+ }
+
+ // Eight character file name
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.pptx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.pptx"), GetLockFileName(aLockFile));
+ }
+
+ // One character file name
+ {
+ OUString aTestFile = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/1.pptx");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$1.pptx"), GetLockFileName(aLockFile));
+ }
+
+ // Test for PPT format
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.ppt");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.ppt"), GetLockFileName(aLockFile));
+ }
+
+ // Test for ODP format
+ {
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/12345678.odp");
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ CPPUNIT_ASSERT_EQUAL(OUString("~$12345678.odp"), GetLockFileName(aLockFile));
+ }
+}
+
+void LockfileTest::testWordLockFileContent()
+{
+ // Test the lockfile generated for the specified DOCX document
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testWordLockFileContent.docx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and check the content
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ aLockFile.CreateOwnLockFile();
+ OUString sLockFileContent(readLockFile(aLockFile.GetURL()));
+ aLockFile.RemoveFileDirectly();
+
+ // First character is the size of the user name
+ OUString sUserName;
+ sUserName += aUserOpt.GetFirstName() + " ";
+ sUserName += aUserOpt.GetLastName();
+ int nIndex = 0;
+ CPPUNIT_ASSERT_EQUAL(sUserName.getLength(), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+
+ // Then we have the user name
+ CPPUNIT_ASSERT_EQUAL(sUserName, sLockFileContent.copy(1, sUserName.getLength()));
+
+ // We have some filling 0 bytes after the user name
+ for (nIndex = sUserName.getLength() + 1; nIndex < MSO_USERNAME_MAX_LENGTH + 2; ++nIndex)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+ }
+
+ // Then we have the user name's length again
+ CPPUNIT_ASSERT_EQUAL(sUserName.getLength(), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+
+ // Then we have the user name again with 16 bit coding
+ for (int i = 0; i < sUserName.getLength(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(
+ sUserName[i],
+ static_cast<sal_Unicode>(static_cast<sal_Int16>(sLockFileContent[55 + i * 2])
+ + static_cast<sal_Int16>(sLockFileContent[55 + i * 2 + 1])));
+ }
+
+ // We have some filling 0 bytes after the user name
+ for (nIndex += sUserName.getLength() * 2 + 1; nIndex < MSO_WORD_LOCKFILE_SIZE; ++nIndex)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+ }
+
+ // We have a fixed size lock file
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(MSO_WORD_LOCKFILE_SIZE), sLockFileContent.getLength());
+}
+
+void LockfileTest::testExcelLockFileContent()
+{
+ // Test the lockfile generated for the specified XLSX document
+ OUString aTestFile
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testExcelLockFileContent.xlsx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and check the content
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ aLockFile.CreateOwnLockFile();
+ OUString sLockFileContent(readLockFile(aLockFile.GetURL()));
+ aLockFile.RemoveFileDirectly();
+
+ // First character is the size of the user name
+ OUString sUserName;
+ sUserName += aUserOpt.GetFirstName() + " ";
+ sUserName += aUserOpt.GetLastName();
+ int nIndex = 0;
+ CPPUNIT_ASSERT_EQUAL(sUserName.getLength(), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+
+ // Then we have the user name
+ CPPUNIT_ASSERT_EQUAL(sUserName, sLockFileContent.copy(1, sUserName.getLength()));
+
+ // We have some filling 0x20 bytes after the user name
+ for (nIndex = sUserName.getLength() + 1; nIndex < MSO_USERNAME_MAX_LENGTH + 3; ++nIndex)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x20), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+ }
+
+ // Then we have the user name's length again
+ CPPUNIT_ASSERT_EQUAL(sUserName.getLength(), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+
+ // Then we have the user name again with 16 bit coding
+ for (int i = 0; i < sUserName.getLength(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(
+ sUserName[i],
+ static_cast<sal_Unicode>(static_cast<sal_Int16>(sLockFileContent[56 + i * 2])
+ + static_cast<sal_Int16>(sLockFileContent[56 + i * 2 + 1])));
+ }
+
+ // We have some filling 0 and 0x20 bytes after the user name
+ for (nIndex += sUserName.getLength() * 2 + 2; nIndex < MSO_EXCEL_AND_POWERPOINT_LOCKFILE_SIZE;
+ nIndex += 2)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x20), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+ if (nIndex + 1 < MSO_EXCEL_AND_POWERPOINT_LOCKFILE_SIZE)
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
+ static_cast<sal_Int32>(sLockFileContent[nIndex + 1]));
+ }
+
+ // We have a fixed size lock file
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(MSO_EXCEL_AND_POWERPOINT_LOCKFILE_SIZE),
+ sLockFileContent.getLength());
+}
+
+void LockfileTest::testPowerPointLockFileContent()
+{
+ // Test the lockfile generated for the specified PPTX document
+ OUString aTestFile = m_directories.getURLFromSrc(
+ "/svl/qa/unit/lockfiles/data/testPowerPointLockFileContent.pptx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and check the content
+ svt::MSODocumentLockFile aLockFile(aTestFile);
+ aLockFile.CreateOwnLockFile();
+ OUString sLockFileContent(readLockFile(aLockFile.GetURL()));
+ aLockFile.RemoveFileDirectly();
+
+ // First character is the size of the user name
+ OUString sUserName;
+ sUserName += aUserOpt.GetFirstName() + " ";
+ sUserName += aUserOpt.GetLastName();
+ int nIndex = 0;
+ CPPUNIT_ASSERT_EQUAL(sUserName.getLength(), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+
+ // Then we have the user name
+ CPPUNIT_ASSERT_EQUAL(sUserName, sLockFileContent.copy(1, sUserName.getLength()));
+
+ // We have some filling bytes after the user name
+ nIndex = sUserName.getLength() + 1;
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+ for (nIndex += 1; nIndex < MSO_USERNAME_MAX_LENGTH + 3; ++nIndex)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x20), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+ }
+
+ // Then we have the user name's length again
+ CPPUNIT_ASSERT_EQUAL(sUserName.getLength(), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+
+ // Then we have the user name again with 16 bit coding
+ for (int i = 0; i < sUserName.getLength(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(
+ sUserName[i],
+ static_cast<sal_Unicode>(static_cast<sal_Int16>(sLockFileContent[56 + i * 2])
+ + static_cast<sal_Int16>(sLockFileContent[56 + i * 2 + 1])));
+ }
+
+ // We have some filling 0 and 0x20 bytes after the user name
+ for (nIndex += sUserName.getLength() * 2 + 2; nIndex < MSO_EXCEL_AND_POWERPOINT_LOCKFILE_SIZE;
+ nIndex += 2)
+ {
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0x20), static_cast<sal_Int32>(sLockFileContent[nIndex]));
+ if (nIndex + 1 < MSO_EXCEL_AND_POWERPOINT_LOCKFILE_SIZE)
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
+ static_cast<sal_Int32>(sLockFileContent[nIndex + 1]));
+ }
+
+ // We have a fixed size lock file
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(MSO_EXCEL_AND_POWERPOINT_LOCKFILE_SIZE),
+ sLockFileContent.getLength());
+}
+
+void LockfileTest::testWordLockFileRT()
+{
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testWordLockFileRT.docx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and read it back
+ svt::MSODocumentLockFile aLockFile(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile.CreateOwnLockFile();
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+ aLockFile.RemoveFileDirectly();
+
+ // Check whether the lock file attributes are the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+}
+
+void LockfileTest::testExcelLockFileRT()
+{
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testExcelLockFileRT.xlsx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and read it back
+ svt::MSODocumentLockFile aLockFile(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile.CreateOwnLockFile();
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+ aLockFile.RemoveFileDirectly();
+
+ // Check whether the lock file attributes are the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+}
+
+void LockfileTest::testPowerPointLockFileRT()
+{
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testPowerPointLockFileRT.pptx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and read it back
+ svt::MSODocumentLockFile aLockFile(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile.CreateOwnLockFile();
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+ aLockFile.RemoveFileDirectly();
+
+ // Check whether the lock file attributes are the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+}
+
+void LockfileTest::testMSOLockFileLongUserName()
+{
+ OUString aTestODT = m_directories.getURLFromSrc(
+ "/svl/qa/unit/lockfiles/data/testMSOLockFileLongUserName.docx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName,
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+ aUserOpt.SetToken(UserOptToken::LastName,
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+
+ // Write the lock file and read it back
+ svt::MSODocumentLockFile aLockFile(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile.CreateOwnLockFile();
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+
+ // Check whether the user name was cut to the maximum length
+ CPPUNIT_ASSERT_EQUAL(
+ aOrigEntry[LockFileComponent::OOOUSERNAME].copy(0, MSO_USERNAME_MAX_LENGTH),
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+
+ aLockFile.RemoveFileDirectly();
+}
+
+void LockfileTest::testMSOLockFileUnicodeUsername()
+{
+ // Test the lockfile generated for the specified ODT document
+ OUString aTestODT = m_directories.getURLFromSrc(
+ "/svl/qa/unit/lockfiles/data/testMSOLockFileUnicodeUsername.docx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ sal_Unicode vFirstName[] = { 2351, 2676, 3117, 5279 };
+ aUserOpt.SetToken(UserOptToken::FirstName, OUString(vFirstName, 4));
+ sal_Unicode vLastName[] = { 671, 1245, 1422, 1822 };
+ aUserOpt.SetToken(UserOptToken::LastName, OUString(vLastName, 4));
+
+ // Write the lock file and read it back
+ svt::DocumentLockFile aLockFile(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile.CreateOwnLockFile();
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+
+ // Check whether the user name is the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+ CPPUNIT_ASSERT_EQUAL(OUString(aUserOpt.GetFirstName() + " " + aUserOpt.GetLastName()),
+ aOrigEntry[LockFileComponent::OOOUSERNAME]);
+
+ aLockFile.RemoveFileDirectly();
+}
+
+void LockfileTest::testMSOLockFileOverwrite()
+{
+ OUString aTestODT
+ = m_directories.getURLFromSrc("/svl/qa/unit/lockfiles/data/testMSOLockFileOverwrite.docx");
+
+ // Set user name
+ SvtUserOptions aUserOpt;
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Write the lock file and read it back
+ svt::MSODocumentLockFile aLockFile(aTestODT);
+ aLockFile.CreateOwnLockFile();
+
+ // Change user name
+ aUserOpt.SetToken(UserOptToken::FirstName, "LockFile2");
+ aUserOpt.SetToken(UserOptToken::LastName, "Test");
+
+ // Overwrite lockfile
+ svt::MSODocumentLockFile aLockFile2(aTestODT);
+ LockFileEntry aOrigEntry = svt::LockFileCommon::GenerateOwnEntry();
+ aLockFile2.OverwriteOwnLockFile();
+
+ LockFileEntry aRTEntry = aLockFile.GetLockData();
+
+ // Check whether the lock file attributes are the same
+ CPPUNIT_ASSERT_EQUAL(aOrigEntry[LockFileComponent::OOOUSERNAME],
+ aRTEntry[LockFileComponent::OOOUSERNAME]);
+
+ aLockFile2.RemoveFileDirectly();
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LockfileTest);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/svl/source/misc/documentlockfile.cxx b/svl/source/misc/documentlockfile.cxx
index 837005bd6f85..1bdf7ce5f386 100644
--- a/svl/source/misc/documentlockfile.cxx
+++ b/svl/source/misc/documentlockfile.cxx
@@ -54,42 +54,34 @@ using namespace ::com::sun::star;
namespace svt {
-bool DocumentLockFile::m_bAllowInteraction = true;
+GenDocumentLockFile::GenDocumentLockFile( const OUString& aURL )
+: LockFileCommon( aURL )
+{
+}
-DocumentLockFile::DocumentLockFile( const OUString& aOrigURL )
-: LockFileCommon( aOrigURL, ".~lock." )
+GenDocumentLockFile::GenDocumentLockFile( const OUString& aOrigURL, const OUString& aPrefix )
+: LockFileCommon( aOrigURL, aPrefix )
{
}
-DocumentLockFile::~DocumentLockFile()
+GenDocumentLockFile::~GenDocumentLockFile()
{
}
-
-void DocumentLockFile::WriteEntryToStream( const LockFileEntry& aEntry, const uno::Reference< io::XOutputStream >& xOutput )
+uno::Reference< io::XInputStream > GenDocumentLockFile::OpenStream()
{
::osl::MutexGuard aGuard( m_aMutex );
- OUStringBuffer aBuffer;
-
- for ( LockFileComponent lft : o3tl::enumrange<LockFileComponent>() )
- {
- aBuffer.append( EscapeCharacters( aEntry[lft] ) );
- if ( lft < LockFileComponent::LAST )
- aBuffer.append( ',' );
- else
- aBuffer.append( ';' );
- }
+ uno::Reference < css::ucb::XCommandEnvironment > xEnv;
+ ::ucbhelper::Content aSourceContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
- OString aStringData( OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ) );
- uno::Sequence< sal_Int8 > aData( reinterpret_cast<sal_Int8 const *>(aStringData.getStr()), aStringData.getLength() );
- xOutput->writeBytes( aData );
+ // the file can be opened readonly, no locking will be done
+ return aSourceContent.openStream();
}
-
-bool DocumentLockFile::CreateOwnLockFile()
+bool GenDocumentLockFile::CreateOwnLockFile()
{
::osl::MutexGuard aGuard( m_aMutex );
@@ -113,7 +105,7 @@ bool DocumentLockFile::CreateOwnLockFile()
xSeekable->seek( 0 );
uno::Reference < css::ucb::XCommandEnvironment > xEnv;
- ::ucbhelper::Content aTargetContent( m_aURL, xEnv, comphelper::getProcessComponentContext() );
+ ::ucbhelper::Content aTargetContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
ucb::InsertCommandArgument aInsertArg;
aInsertArg.Data = xInput;
@@ -135,50 +127,13 @@ bool DocumentLockFile::CreateOwnLockFile()
return true;
}
-
-LockFileEntry DocumentLockFile::GetLockData()
-{
- ::osl::MutexGuard aGuard( m_aMutex );
-
- uno::Reference< io::XInputStream > xInput = OpenStream();
- if ( !xInput.is() )
- throw uno::RuntimeException();
-
- const sal_Int32 nBufLen = 32000;
- uno::Sequence< sal_Int8 > aBuffer( nBufLen );
-
- sal_Int32 nRead = 0;
-
- nRead = xInput->readBytes( aBuffer, nBufLen );
- xInput->closeInput();
-
- if ( nRead == nBufLen )
- throw io::WrongFormatException();
-
- sal_Int32 nCurPos = 0;
- return ParseEntry( aBuffer, nCurPos );
-}
-
-
-uno::Reference< io::XInputStream > DocumentLockFile::OpenStream()
-{
- ::osl::MutexGuard aGuard( m_aMutex );
-
- uno::Reference < css::ucb::XCommandEnvironment > xEnv;
- ::ucbhelper::Content aSourceContent( m_aURL, xEnv, comphelper::getProcessComponentContext() );
-
- // the file can be opened readonly, no locking will be done
- return aSourceContent.openStream();
-}
-
-
-bool DocumentLockFile::OverwriteOwnLockFile()
+bool GenDocumentLockFile::OverwriteOwnLockFile()
{
// allows to overwrite the lock file with the current data
try
{
uno::Reference < css::ucb::XCommandEnvironment > xEnv;
- ::ucbhelper::Content aTargetContent( m_aURL, xEnv, comphelper::getProcessComponentContext() );
+ ::ucbhelper::Content aTargetContent( GetURL(), xEnv, comphelper::getProcessComponentContext() );
LockFileEntry aNewEntry = GenerateOwnEntry();
@@ -198,8 +153,7 @@ bool DocumentLockFile::OverwriteOwnLockFile()
return true;
}
-
-void DocumentLockFile::RemoveFile()
+void GenDocumentLockFile::RemoveFile()
{
::osl::MutexGuard aGuard( m_aMutex );
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list