1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include "moduldlg.hxx"
22 #include <basidesh.hxx>
23 #include <strings.hrc>
24 #include <bitmaps.hlst>
25 #include <iderdll.hxx>
26 #include "iderdll2.hxx"
27 #include <svx/passwd.hxx>
28 #include <ucbhelper/content.hxx>
29 #include <rtl/uri.hxx>
30 #include <sfx2/app.hxx>
31 #include <sfx2/dinfdlg.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/filedlghelper.hxx>
34 #include <sfx2/request.hxx>
35 #include <sfx2/sfxsids.hrc>
36 #include <sfx2/viewfrm.hxx>
37 #include <tools/debug.hxx>
38 #include <tools/urlobj.hxx>
39 #include <tools/diagnose_ex.h>
40 #include <vcl/svapp.hxx>
41 #include <vcl/weld.hxx>
42 
43 #include <com/sun/star/io/Pipe.hpp>
44 #include <com/sun/star/ui/dialogs/FilePicker.hpp>
45 #include <com/sun/star/ui/dialogs/FolderPicker.hpp>
46 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
47 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
48 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
49 #include <com/sun/star/script/XLibraryContainerPassword.hpp>
50 #include <com/sun/star/script/XLibraryContainerExport.hpp>
51 #include <com/sun/star/task/InteractionHandler.hpp>
52 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
53 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
54 #include <com/sun/star/ucb/NameClash.hpp>
55 #include <com/sun/star/packages/manifest/ManifestWriter.hpp>
56 #include <unotools/pathoptions.hxx>
57 
58 #include <com/sun/star/util/VetoException.hpp>
59 #include <com/sun/star/script/ModuleSizeExceededRequest.hpp>
60 
61 #include <comphelper/processfactory.hxx>
62 #include <comphelper/propertysequence.hxx>
63 #include <cppuhelper/implbase.hxx>
64 
65 #include <cassert>
66 
67 namespace basctl
68 {
69 
70 using namespace ::com::sun::star;
71 using namespace ::com::sun::star::uno;
72 using namespace ::com::sun::star::lang;
73 using namespace ::com::sun::star::ucb;
74 using namespace ::com::sun::star::ui::dialogs;
75 
76 namespace
77 {
78 
79 class DummyInteractionHandler  : public ::cppu::WeakImplHelper< task::XInteractionHandler >
80 {
81     Reference< task::XInteractionHandler2 > m_xHandler;
82 public:
DummyInteractionHandler(const Reference<task::XInteractionHandler2> & xHandler)83     explicit DummyInteractionHandler(const Reference<task::XInteractionHandler2>& xHandler)
84         : m_xHandler(xHandler)
85     {
86     }
87 
handle(const Reference<task::XInteractionRequest> & rRequest)88     virtual void SAL_CALL handle( const Reference< task::XInteractionRequest >& rRequest ) override
89     {
90         if ( m_xHandler.is() )
91         {
92         script::ModuleSizeExceededRequest aModSizeException;
93         if ( rRequest->getRequest() >>= aModSizeException )
94             m_xHandler->handle( rRequest );
95         }
96     }
97 };
98 
99 } // namespace
100 
101 namespace
102 {
FindEntry(const weld::TreeView & rBox,const OUString & rName)103     int FindEntry(const weld::TreeView& rBox, const OUString& rName)
104     {
105         int nCount = rBox.n_children();
106         for (int i = 0; i < nCount; ++i)
107         {
108             if (rName.equalsIgnoreAsciiCase(rBox.get_text(i, 0)))
109                 return i;
110         }
111         return -1;
112     }
113 }
114 
115 // NewObjectDialog
IMPL_LINK_NOARG(NewObjectDialog,OkButtonHandler,weld::Button &,void)116 IMPL_LINK_NOARG(NewObjectDialog, OkButtonHandler, weld::Button&, void)
117 {
118     if (!m_bCheckName || IsValidSbxName(m_xEdit->get_text()))
119         m_xDialog->response(RET_OK);
120     else
121     {
122         std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(),
123                                                        VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME)));
124         xErrorBox->run();
125         m_xEdit->grab_focus();
126     }
127 }
128 
NewObjectDialog(weld::Window * pParent,ObjectMode eMode,bool bCheckName)129 NewObjectDialog::NewObjectDialog(weld::Window * pParent, ObjectMode eMode, bool bCheckName)
130     : GenericDialogController(pParent, "modules/BasicIDE/ui/newlibdialog.ui", "NewLibDialog")
131     , m_xEdit(m_xBuilder->weld_entry("entry"))
132     , m_xOKButton(m_xBuilder->weld_button("ok"))
133     , m_bCheckName(bCheckName)
134 {
135     switch (eMode)
136     {
137         case ObjectMode::Library:
138             m_xDialog->set_title(IDEResId(RID_STR_NEWLIB));
139             break;
140         case ObjectMode::Module:
141             m_xDialog->set_title(IDEResId(RID_STR_NEWMOD));
142             break;
143         case ObjectMode::Dialog:
144             m_xDialog->set_title(IDEResId(RID_STR_NEWDLG));
145             break;
146         default:
147             assert(false);
148     }
149     m_xOKButton->connect_clicked(LINK(this, NewObjectDialog, OkButtonHandler));
150 }
151 
152 // GotoLineDialog
GotoLineDialog(weld::Window * pParent)153 GotoLineDialog::GotoLineDialog(weld::Window* pParent )
154     : GenericDialogController(pParent, "modules/BasicIDE/ui/gotolinedialog.ui", "GotoLineDialog")
155     , m_xEdit(m_xBuilder->weld_entry("entry"))
156     , m_xOKButton(m_xBuilder->weld_button("ok"))
157 {
158     m_xEdit->grab_focus();
159     m_xOKButton->connect_clicked(LINK(this, GotoLineDialog, OkButtonHandler));
160 }
161 
~GotoLineDialog()162 GotoLineDialog::~GotoLineDialog()
163 {
164 }
165 
GetLineNumber() const166 sal_Int32 GotoLineDialog::GetLineNumber() const
167 {
168     return m_xEdit->get_text().toInt32();
169 }
170 
IMPL_LINK_NOARG(GotoLineDialog,OkButtonHandler,weld::Button &,void)171 IMPL_LINK_NOARG(GotoLineDialog, OkButtonHandler, weld::Button&, void)
172 {
173     if (GetLineNumber())
174         m_xDialog->response(RET_OK);
175     else
176         m_xEdit->select_region(0, -1);
177 }
178 
179 // ExportDialog
IMPL_LINK_NOARG(ExportDialog,OkButtonHandler,weld::Button &,void)180 IMPL_LINK_NOARG(ExportDialog, OkButtonHandler, weld::Button&, void)
181 {
182     m_bExportAsPackage = m_xExportAsPackageButton->get_active();
183     m_xDialog->response(RET_OK);
184 }
185 
ExportDialog(weld::Window * pParent)186 ExportDialog::ExportDialog(weld::Window * pParent)
187     : GenericDialogController(pParent, "modules/BasicIDE/ui/exportdialog.ui", "ExportDialog")
188     , m_bExportAsPackage(false)
189     , m_xExportAsPackageButton(m_xBuilder->weld_radio_button("extension"))
190     , m_xOKButton(m_xBuilder->weld_button("ok"))
191 {
192     m_xExportAsPackageButton->set_active(true);
193     m_xOKButton->connect_clicked(LINK(this, ExportDialog, OkButtonHandler));
194 }
195 
~ExportDialog()196 ExportDialog::~ExportDialog()
197 {
198 }
199 
200 // LibPage
LibPage(weld::Container * pParent,OrganizeDialog * pDialog)201 LibPage::LibPage(weld::Container* pParent, OrganizeDialog* pDialog)
202     : OrganizePage(pParent, "modules/BasicIDE/ui/libpage.ui", "LibPage", pDialog)
203     , m_xBasicsBox(m_xBuilder->weld_combo_box("location"))
204     , m_xLibBox(m_xBuilder->weld_tree_view("library"))
205     , m_xEditButton(m_xBuilder->weld_button("edit"))
206     , m_xPasswordButton(m_xBuilder->weld_button("password"))
207     , m_xNewLibButton(m_xBuilder->weld_button("new"))
208     , m_xInsertLibButton(m_xBuilder->weld_button("import"))
209     , m_xExportButton(m_xBuilder->weld_button("export"))
210     , m_xDelButton(m_xBuilder->weld_button("delete"))
211     , m_aCurDocument(ScriptDocument::getApplicationScriptDocument())
212     , m_eCurLocation(LIBRARY_LOCATION_UNKNOWN)
213 {
214     Size aSize(m_xLibBox->get_approximate_digit_width() * 40,
215                m_xLibBox->get_height_rows(10));
216     m_xLibBox->set_size_request(aSize.Width(), aSize.Height());
217 
218     // tdf#93476 The libraries should be listed alphabetically
219     m_xLibBox->make_sorted();
220 
221     m_xEditButton->connect_clicked( LINK( this, LibPage, ButtonHdl ) );
222     m_xNewLibButton->connect_clicked( LINK( this, LibPage, ButtonHdl ) );
223     m_xPasswordButton->connect_clicked( LINK( this, LibPage, ButtonHdl ) );
224     m_xExportButton->connect_clicked( LINK( this, LibPage, ButtonHdl ) );
225     m_xInsertLibButton->connect_clicked( LINK( this, LibPage, ButtonHdl ) );
226     m_xDelButton->connect_clicked( LINK( this, LibPage, ButtonHdl ) );
227     m_xLibBox->connect_changed( LINK( this, LibPage, TreeListHighlightHdl ) );
228 
229     m_xBasicsBox->connect_changed( LINK( this, LibPage, BasicSelectHdl ) );
230 
231     m_xLibBox->connect_editing(LINK(this, LibPage, EditingEntryHdl),
232                                LINK(this, LibPage, EditedEntryHdl));
233 
234     FillListBox();
235     m_xBasicsBox->set_active(0);
236     SetCurLib();
237 
238     CheckButtons();
239 }
240 
IMPL_LINK(LibPage,EditingEntryHdl,const weld::TreeIter &,rIter,bool)241 IMPL_LINK(LibPage, EditingEntryHdl, const weld::TreeIter&, rIter, bool)
242 {
243     // check, if Standard library
244     OUString aLibName = m_xLibBox->get_text(rIter, 0);
245 
246     if ( aLibName.equalsIgnoreAsciiCase( "Standard" ) )
247     {
248         std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
249                                                        VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_CANNOTCHANGENAMESTDLIB)));
250         xErrorBox->run();
251         return false;
252     }
253 
254     // check, if library is readonly
255     Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
256     Reference< script::XLibraryContainer2 > xDlgLibContainer( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY );
257     if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryReadOnly( aLibName ) && !xModLibContainer->isLibraryLink( aLibName ) ) ||
258          ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryReadOnly( aLibName ) && !xDlgLibContainer->isLibraryLink( aLibName ) ) )
259     {
260         std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
261                                                        VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_LIBISREADONLY)));
262         xErrorBox->run();
263         return false;
264     }
265 
266     // i24094: Password verification necessary for renaming
267     if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && !xModLibContainer->isLibraryLoaded( aLibName ) )
268     {
269         bool bOK = true;
270         // check password
271         Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
272         if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aLibName ) && !xPasswd->isLibraryPasswordVerified( aLibName ) )
273         {
274             OUString aPassword;
275             bOK = QueryPassword(m_pDialog->getDialog(), xModLibContainer, aLibName, aPassword);
276         }
277         if ( !bOK )
278             return false;
279     }
280 
281     // TODO: check if library is reference/link
282 
283     return true;
284 }
285 
IMPL_LINK(LibPage,EditedEntryHdl,const IterString &,rIterString,bool)286 IMPL_LINK(LibPage, EditedEntryHdl, const IterString&, rIterString, bool)
287 {
288     const weld::TreeIter& rIter = rIterString.first;
289     OUString sNewName = rIterString.second;
290 
291     bool bValid = sNewName.getLength() <= 30 && IsValidSbxName(sNewName);
292     OUString aOldName(m_xLibBox->get_text(rIter, 0));
293 
294     if (bValid && aOldName != sNewName)
295     {
296         try
297         {
298             Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
299             if ( xModLibContainer.is() )
300                 xModLibContainer->renameLibrary( aOldName, sNewName );
301 
302             Reference< script::XLibraryContainer2 > xDlgLibContainer( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY );
303             if ( xDlgLibContainer.is() )
304                 xDlgLibContainer->renameLibrary( aOldName, sNewName );
305 
306             MarkDocumentModified( m_aCurDocument );
307             if (SfxBindings* pBindings = GetBindingsPtr())
308             {
309                 pBindings->Invalidate( SID_BASICIDE_LIBSELECTOR );
310                 pBindings->Update( SID_BASICIDE_LIBSELECTOR );
311             }
312         }
313         catch (const container::ElementExistException& )
314         {
315             std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
316                                                            VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_SBXNAMEALLREADYUSED)));
317             xErrorBox->run();
318             return false;
319         }
320         catch (const container::NoSuchElementException& )
321         {
322             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
323             return false;
324         }
325     }
326 
327     if ( !bValid )
328     {
329         OUString sWarning(sNewName.getLength() > 30 ? IDEResId(RID_STR_LIBNAMETOLONG) : IDEResId(RID_STR_BADSBXNAME));
330         std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
331                                                        VclMessageType::Warning, VclButtonsType::Ok, sWarning));
332         xErrorBox->run();
333 
334     }
335 
336     return bValid;
337 }
338 
~LibPage()339 LibPage::~LibPage()
340 {
341     if (m_xBasicsBox)
342     {
343         const sal_Int32 nCount = m_xBasicsBox->get_count();
344         for (sal_Int32 i = 0; i < nCount; ++i)
345         {
346             DocumentEntry* pEntry = reinterpret_cast<DocumentEntry*>(m_xBasicsBox->get_id(i).toInt64());
347             delete pEntry;
348         }
349     }
350 }
351 
CheckButtons()352 void LibPage::CheckButtons()
353 {
354     std::unique_ptr<weld::TreeIter> xCur(m_xLibBox->make_iterator());
355     if (m_xLibBox->get_cursor(xCur.get()))
356     {
357         OUString aLibName = m_xLibBox->get_text(*xCur, 0);
358         Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
359         Reference< script::XLibraryContainer2 > xDlgLibContainer( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY );
360 
361         if ( m_eCurLocation == LIBRARY_LOCATION_SHARE )
362         {
363             m_xPasswordButton->set_sensitive(false);
364             m_xNewLibButton->set_sensitive(false);
365             m_xInsertLibButton->set_sensitive(false);
366             m_xDelButton->set_sensitive(false);
367         }
368         else if ( aLibName.equalsIgnoreAsciiCase( "Standard" ) )
369         {
370             m_xPasswordButton->set_sensitive(false);
371             m_xNewLibButton->set_sensitive(true);
372             m_xInsertLibButton->set_sensitive(true);
373             m_xExportButton->set_sensitive(false);
374             m_xDelButton->set_sensitive(false);
375         }
376         else if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryReadOnly( aLibName ) ) ||
377                   ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryReadOnly( aLibName ) ) )
378         {
379             m_xPasswordButton->set_sensitive(false);
380             m_xNewLibButton->set_sensitive(true);
381             m_xInsertLibButton->set_sensitive(true);
382             if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryReadOnly( aLibName ) && !xModLibContainer->isLibraryLink( aLibName ) ) ||
383                  ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryReadOnly( aLibName ) && !xDlgLibContainer->isLibraryLink( aLibName ) ) )
384                 m_xDelButton->set_sensitive(false);
385             else
386                 m_xDelButton->set_sensitive(true);
387         }
388         else
389         {
390             if ( xModLibContainer.is() && !xModLibContainer->hasByName( aLibName ) )
391                 m_xPasswordButton->set_sensitive(false);
392             else
393                 m_xPasswordButton->set_sensitive(true);
394 
395             m_xNewLibButton->set_sensitive(true);
396             m_xInsertLibButton->set_sensitive(true);
397             m_xExportButton->set_sensitive(true);
398             m_xDelButton->set_sensitive(true);
399         }
400     }
401 }
402 
ActivatePage()403 void LibPage::ActivatePage()
404 {
405     SetCurLib();
406 }
407 
IMPL_LINK_NOARG(LibPage,TreeListHighlightHdl,weld::TreeView &,void)408 IMPL_LINK_NOARG(LibPage, TreeListHighlightHdl, weld::TreeView&, void)
409 {
410     CheckButtons();
411 }
412 
IMPL_LINK_NOARG(LibPage,BasicSelectHdl,weld::ComboBox &,void)413 IMPL_LINK_NOARG( LibPage, BasicSelectHdl, weld::ComboBox&, void )
414 {
415     SetCurLib();
416     CheckButtons();
417 }
418 
IMPL_LINK(LibPage,ButtonHdl,weld::Button &,rButton,void)419 IMPL_LINK( LibPage, ButtonHdl, weld::Button&, rButton, void )
420 {
421     if (&rButton == m_xEditButton.get())
422     {
423         SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
424         SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs );
425         SfxGetpApp()->ExecuteSlot( aRequest );
426 
427         SfxUnoAnyItem aDocItem( SID_BASICIDE_ARG_DOCUMENT_MODEL, Any( m_aCurDocument.getDocumentOrNull() ) );
428 
429         std::unique_ptr<weld::TreeIter> xCurEntry(m_xLibBox->make_iterator());
430         if (!m_xLibBox->get_cursor(xCurEntry.get()))
431             return;
432         OUString aLibName(m_xLibBox->get_text(*xCurEntry, 0));
433         SfxStringItem aLibNameItem( SID_BASICIDE_ARG_LIBNAME, aLibName );
434         if (SfxDispatcher* pDispatcher = GetDispatcher())
435             pDispatcher->ExecuteList( SID_BASICIDE_LIBSELECTED,
436                 SfxCallMode::ASYNCHRON, { &aDocItem, &aLibNameItem });
437         EndTabDialog();
438         return;
439     }
440     else if (&rButton == m_xNewLibButton.get())
441         NewLib();
442     else if (&rButton == m_xInsertLibButton.get())
443         InsertLib();
444     else if (&rButton == m_xExportButton.get())
445         Export();
446     else if (&rButton == m_xDelButton.get())
447         DeleteCurrent();
448     else if (&rButton == m_xPasswordButton.get())
449     {
450         std::unique_ptr<weld::TreeIter> xCurEntry(m_xLibBox->make_iterator());
451         if (!m_xLibBox->get_cursor(xCurEntry.get()))
452             return;
453         OUString aLibName(m_xLibBox->get_text(*xCurEntry, 0));
454 
455         // load module library (if not loaded)
456         Reference< script::XLibraryContainer > xModLibContainer = m_aCurDocument.getLibraryContainer( E_SCRIPTS );
457         if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && !xModLibContainer->isLibraryLoaded( aLibName ) )
458         {
459             Shell* pShell = GetShell();
460             if (pShell)
461                 pShell->GetViewFrame()->GetWindow().EnterWait();
462             xModLibContainer->loadLibrary( aLibName );
463             if (pShell)
464                 pShell->GetViewFrame()->GetWindow().LeaveWait();
465         }
466 
467         // load dialog library (if not loaded)
468         Reference< script::XLibraryContainer > xDlgLibContainer = m_aCurDocument.getLibraryContainer( E_DIALOGS );
469         if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && !xDlgLibContainer->isLibraryLoaded( aLibName ) )
470         {
471             Shell* pShell = GetShell();
472             if (pShell)
473                 pShell->GetViewFrame()->GetWindow().EnterWait();
474             xDlgLibContainer->loadLibrary( aLibName );
475             if (pShell)
476                 pShell->GetViewFrame()->GetWindow().LeaveWait();
477         }
478 
479         // check, if library is password protected
480         if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) )
481         {
482             Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
483             if ( xPasswd.is() )
484             {
485                 bool const bProtected = xPasswd->isLibraryPasswordProtected( aLibName );
486 
487                 // change password dialog
488                 SvxPasswordDialog aDlg(m_pDialog->getDialog(), !bProtected);
489                 aDlg.SetCheckPasswordHdl(LINK(this, LibPage, CheckPasswordHdl));
490 
491                 if (aDlg.run() == RET_OK)
492                 {
493                     bool const bNewProtected = xPasswd->isLibraryPasswordProtected( aLibName );
494 
495                     if ( bNewProtected != bProtected )
496                     {
497                         int nPos = m_xLibBox->get_iter_index_in_parent(*xCurEntry);
498                         m_xLibBox->remove(*xCurEntry);
499                         ImpInsertLibEntry(aLibName, nPos);
500                         m_xLibBox->set_cursor(nPos);
501                     }
502 
503                     MarkDocumentModified( m_aCurDocument );
504                 }
505             }
506         }
507     }
508     CheckButtons();
509 }
510 
IMPL_LINK(LibPage,CheckPasswordHdl,SvxPasswordDialog *,pDlg,bool)511 IMPL_LINK( LibPage, CheckPasswordHdl, SvxPasswordDialog *, pDlg, bool )
512 {
513     bool bRet = false;
514 
515     std::unique_ptr<weld::TreeIter> xCurEntry(m_xLibBox->make_iterator());
516     if (!m_xLibBox->get_cursor(xCurEntry.get()))
517         return bRet;
518 
519     OUString aLibName(m_xLibBox->get_text(*xCurEntry, 0));
520     Reference< script::XLibraryContainerPassword > xPasswd( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
521 
522     if ( xPasswd.is() )
523     {
524         try
525         {
526             OUString aOldPassword( pDlg->GetOldPassword() );
527             OUString aNewPassword( pDlg->GetNewPassword() );
528             xPasswd->changeLibraryPassword( aLibName, aOldPassword, aNewPassword );
529             bRet = true;
530         }
531         catch (...)
532         {
533         }
534     }
535 
536     return bRet;
537 }
538 
NewLib()539 void LibPage::NewLib()
540 {
541     createLibImpl(m_pDialog->getDialog(), m_aCurDocument, m_xLibBox.get(), nullptr);
542 }
543 
InsertLib()544 void LibPage::InsertLib()
545 {
546     Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
547     // file open dialog
548     sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, m_pDialog->getDialog());
549     const Reference <XFilePicker3>& xFP = aDlg.GetFilePicker();
550 
551     xFP->setTitle(IDEResId(RID_STR_APPENDLIBS));
552 
553     // filter
554     OUString aTitle(IDEResId(RID_STR_BASIC));
555     OUString aFilter = "*.sbl;*.xlc;*.xlb"        // library files
556               ";*.sdw;*.sxw;*.odt"       // text
557               ";*.vor;*.stw;*.ott"       // text template
558               ";*.sgl;*.sxg;*.odm"       // master document
559               ";*.oth"                   // html document template
560               ";*.sdc;*.sxc;*.ods"       // spreadsheet
561               ";*.stc;*.ots"             // spreadsheet template
562               ";*.sda;*.sxd;*.odg"       // drawing
563               ";*.std;*.otg"             // drawing template
564               ";*.sdd;*.sxi;*.odp"       // presentation
565               ";*.sti;*.otp"             // presentation template
566               ";*.sxm;*.odf";            // formula
567     xFP->appendFilter( aTitle, aFilter );
568 
569     // set display directory and filter
570     OUString aPath(GetExtraData()->GetAddLibPath());
571     if ( !aPath.isEmpty() )
572         xFP->setDisplayDirectory( aPath );
573     else
574     {
575         // macro path from configuration management
576         xFP->setDisplayDirectory( SvtPathOptions().GetWorkPath() );
577     }
578 
579     OUString aLastFilter(GetExtraData()->GetAddLibFilter());
580     if ( !aLastFilter.isEmpty() )
581         xFP->setCurrentFilter( aLastFilter );
582     else
583         xFP->setCurrentFilter( IDEResId(RID_STR_BASIC) );
584 
585     if ( xFP->execute() != RET_OK )
586             return;
587 
588     GetExtraData()->SetAddLibPath( xFP->getDisplayDirectory() );
589     GetExtraData()->SetAddLibFilter( xFP->getCurrentFilter() );
590 
591     // library containers for import
592     Reference< script::XLibraryContainer2 > xModLibContImport;
593     Reference< script::XLibraryContainer2 > xDlgLibContImport;
594 
595     // file URLs
596     Sequence< OUString > aFiles = xFP->getSelectedFiles();
597     INetURLObject aURLObj( aFiles[0] );
598     std::shared_ptr<INetURLObject> xModURLObj(new INetURLObject(aURLObj));
599     std::shared_ptr<INetURLObject> xDlgURLObj(new INetURLObject(aURLObj));
600 
601     OUString aBase = aURLObj.getBase();
602     OUString aModBase( "script" );
603     OUString aDlgBase( "dialog" );
604 
605     if ( aBase == aModBase || aBase == aDlgBase )
606     {
607         xModURLObj->setBase( aModBase );
608         xDlgURLObj->setBase( aDlgBase );
609     }
610 
611     Reference< XSimpleFileAccess3 > xSFA( SimpleFileAccess::create(comphelper::getProcessComponentContext()) );
612 
613     OUString aModURL( xModURLObj->GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
614     if ( xSFA->exists( aModURL ) )
615     {
616         xModLibContImport = script::DocumentScriptLibraryContainer::createWithURL(xContext, aModURL);
617     }
618 
619     OUString aDlgURL( xDlgURLObj->GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
620     if ( xSFA->exists( aDlgURL ) )
621     {
622         xDlgLibContImport = script::DocumentDialogLibraryContainer::createWithURL(xContext, aDlgURL);
623     }
624 
625     if ( !xModLibContImport.is() && !xDlgLibContImport.is() )
626         return;
627 
628     std::shared_ptr<LibDialog> xLibDlg;
629 
630     Sequence< OUString > aLibNames = GetMergedLibraryNames( xModLibContImport, xDlgLibContImport );
631     sal_Int32 nLibCount = aLibNames.getLength();
632     const OUString* pLibNames = aLibNames.getConstArray();
633     for ( sal_Int32 i = 0 ; i < nLibCount ; i++ )
634     {
635         // library import dialog
636         if (!xLibDlg)
637         {
638             xLibDlg.reset(new LibDialog(m_pDialog->getDialog()));
639             xLibDlg->SetStorageName( aURLObj.getName() );
640         }
641 
642         // libbox entries
643         OUString aLibName( pLibNames[ i ] );
644         if ( !( ( xModLibContImport.is() && xModLibContImport->hasByName( aLibName ) && xModLibContImport->isLibraryLink( aLibName ) ) ||
645                 ( xDlgLibContImport.is() && xDlgLibContImport->hasByName( aLibName ) && xDlgLibContImport->isLibraryLink( aLibName ) ) ) )
646         {
647             weld::TreeView& rView = xLibDlg->GetLibBox();
648             rView.append();
649             const int nRow = rView.n_children() - 1;
650             rView.set_toggle(nRow, TRISTATE_TRUE, 0);
651             rView.set_text(nRow, aLibName, 1);
652             rView.set_cursor(rView.find_text(aLibName));
653         }
654     }
655 
656     if (!xLibDlg)
657     {
658         std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
659                                                        VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_NOLIBINSTORAGE)));
660         xErrorBox->run();
661         return;
662     }
663 
664     OUString aExtension( aURLObj.getExtension() );
665     OUString aLibExtension( "xlb" );
666     OUString aContExtension( "xlc" );
667 
668     // disable reference checkbox for documents and sbls
669     if ( aExtension != aLibExtension && aExtension != aContExtension )
670         xLibDlg->EnableReference(false);
671 
672     weld::DialogController::runAsync(xLibDlg, [aContExtension, xDlgURLObj, aExtension, aLibExtension, xModURLObj, xLibDlg, xDlgLibContImport, xModLibContImport, this](sal_Int32 nResult)
673         {
674             if (!nResult )
675                 return;
676 
677             bool bChanges = false;
678             bool bRemove = false;
679             bool bReplace = xLibDlg->IsReplace();
680             bool bReference = xLibDlg->IsReference();
681             weld::TreeView& rView = xLibDlg->GetLibBox();
682             for (int nLib = 0, nChildren = rView.n_children(); nLib < nChildren; ++nLib)
683             {
684                 if (rView.get_toggle(nLib, 0) == TRISTATE_TRUE)
685                 {
686                     OUString aLibName(rView.get_text(nLib, 1));
687                     Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
688                     Reference< script::XLibraryContainer2 > xDlgLibContainer( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY );
689 
690                     // check, if the library is already existing
691                     if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) ) ||
692                          ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) ) )
693                     {
694                         if ( bReplace )
695                         {
696                             // check, if the library is the Standard library
697                             if ( aLibName == "Standard" )
698                             {
699                                 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
700                                                                                VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_REPLACESTDLIB)));
701                                 xErrorBox->run();
702                                 continue;
703                             }
704 
705                             // check, if the library is readonly and not a link
706                             if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryReadOnly( aLibName ) && !xModLibContainer->isLibraryLink( aLibName ) ) ||
707                                  ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryReadOnly( aLibName ) && !xDlgLibContainer->isLibraryLink( aLibName ) ) )
708                             {
709                                 OUString aErrStr( IDEResId(RID_STR_REPLACELIB) );
710                                 aErrStr = aErrStr.replaceAll("XX", aLibName) + "\n" + IDEResId(RID_STR_LIBISREADONLY);
711                                 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
712                                                                                VclMessageType::Warning, VclButtonsType::Ok, aErrStr));
713                                 xErrorBox->run();
714                                 continue;
715                             }
716 
717                             // remove existing libraries
718                             bRemove = true;
719                         }
720                         else
721                         {
722                             OUString aErrStr;
723                             if ( bReference )
724                                 aErrStr = IDEResId(RID_STR_REFNOTPOSSIBLE);
725                             else
726                                 aErrStr = IDEResId(RID_STR_IMPORTNOTPOSSIBLE);
727                             aErrStr = aErrStr.replaceAll("XX", aLibName) + "\n" +IDEResId(RID_STR_SBXNAMEALLREADYUSED);
728                             std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
729                                                                            VclMessageType::Warning, VclButtonsType::Ok, aErrStr));
730                             xErrorBox->run();
731                             continue;
732                         }
733                     }
734 
735                     // check, if the library is password protected
736                     bool bOK = false;
737                     OUString aPassword;
738                     if ( xModLibContImport.is() && xModLibContImport->hasByName( aLibName ) )
739                     {
740                         Reference< script::XLibraryContainerPassword > xPasswd( xModLibContImport, UNO_QUERY );
741                         if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aLibName ) && !xPasswd->isLibraryPasswordVerified( aLibName ) && !bReference )
742                         {
743                             bOK = QueryPassword(m_pDialog->getDialog(), xModLibContImport, aLibName, aPassword, true, true);
744 
745                             if ( !bOK )
746                             {
747                                 OUString aErrStr( IDEResId(RID_STR_NOIMPORT) );
748                                 aErrStr = aErrStr.replaceAll("XX", aLibName);
749                                 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDialog->getDialog(),
750                                                                                VclMessageType::Warning, VclButtonsType::Ok, aErrStr));
751                                 xErrorBox->run();
752                                 continue;
753                             }
754                         }
755                     }
756 
757                     // remove existing libraries
758                     if ( bRemove )
759                     {
760                         // remove listbox entry
761                         int nEntry_ = FindEntry(*m_xLibBox, aLibName);
762                         if (nEntry_ != -1)
763                             m_xLibBox->remove(nEntry_);
764 
765                         // remove module library
766                         if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) )
767                             xModLibContainer->removeLibrary( aLibName );
768 
769                         // remove dialog library
770                         if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) )
771                             xDlgLibContainer->removeLibrary( aLibName );
772                     }
773 
774                     // copy module library
775                     if ( xModLibContImport.is() && xModLibContImport->hasByName( aLibName ) && xModLibContainer.is() && !xModLibContainer->hasByName( aLibName ) )
776                     {
777                         Reference< container::XNameContainer > xModLib;
778                         if ( bReference )
779                         {
780                             // storage URL
781                             INetURLObject aModStorageURLObj(*xModURLObj);
782                             if ( aExtension == aContExtension )
783                             {
784                                 sal_Int32 nCount = aModStorageURLObj.getSegmentCount();
785                                 aModStorageURLObj.insertName( aLibName, false, nCount-1 );
786                                 aModStorageURLObj.setExtension( aLibExtension );
787                                 aModStorageURLObj.setFinalSlash();
788                             }
789                             OUString aModStorageURL( aModStorageURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
790 
791                             // create library link
792                             xModLib.set( xModLibContainer->createLibraryLink( aLibName, aModStorageURL, true ), UNO_QUERY);
793                         }
794                         else
795                         {
796                             // create library
797                             xModLib = xModLibContainer->createLibrary( aLibName );
798                             if ( xModLib.is() )
799                             {
800                                 // get import library
801                                 Reference< container::XNameContainer > xModLibImport;
802                                 Any aElement = xModLibContImport->getByName( aLibName );
803                                 aElement >>= xModLibImport;
804 
805                                 if ( xModLibImport.is() )
806                                 {
807                                     // load library
808                                     if ( !xModLibContImport->isLibraryLoaded( aLibName ) )
809                                         xModLibContImport->loadLibrary( aLibName );
810 
811                                     // copy all modules
812                                     Sequence< OUString > aModNames = xModLibImport->getElementNames();
813                                     sal_Int32 nModCount = aModNames.getLength();
814                                     const OUString* pModNames = aModNames.getConstArray();
815                                     for ( sal_Int32 i = 0 ; i < nModCount ; i++ )
816                                     {
817                                         OUString aModName( pModNames[ i ] );
818                                         Any aElement_ = xModLibImport->getByName( aModName );
819                                         xModLib->insertByName( aModName, aElement_ );
820                                     }
821 
822                                     // set password
823                                     if ( bOK )
824                                     {
825                                         Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
826                                         if ( xPasswd.is() )
827                                         {
828                                             try
829                                             {
830                                                 xPasswd->changeLibraryPassword( aLibName, OUString(), aPassword );
831                                             }
832                                             catch (...)
833                                             {
834                                             }
835                                         }
836                                     }
837                                 }
838                             }
839                         }
840                     }
841 
842                     // copy dialog library
843                     if ( xDlgLibContImport.is() && xDlgLibContImport->hasByName( aLibName ) && xDlgLibContainer.is() && !xDlgLibContainer->hasByName( aLibName ) )
844                     {
845                         Reference< container::XNameContainer > xDlgLib;
846                         if ( bReference )
847                         {
848                             // storage URL
849                             INetURLObject aDlgStorageURLObj( *xDlgURLObj );
850                             if ( aExtension == aContExtension )
851                             {
852                                 sal_Int32 nCount = aDlgStorageURLObj.getSegmentCount();
853                                 aDlgStorageURLObj.insertName( aLibName, false, nCount - 1 );
854                                 aDlgStorageURLObj.setExtension( aLibExtension );
855                                 aDlgStorageURLObj.setFinalSlash();
856                             }
857                             OUString aDlgStorageURL( aDlgStorageURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
858 
859                             // create library link
860                             xDlgLib.set( xDlgLibContainer->createLibraryLink( aLibName, aDlgStorageURL, true ), UNO_QUERY);
861                         }
862                         else
863                         {
864                             // create library
865                             xDlgLib = xDlgLibContainer->createLibrary( aLibName );
866                             if ( xDlgLib.is() )
867                             {
868                                 // get import library
869                                 Reference< container::XNameContainer > xDlgLibImport;
870                                 Any aElement = xDlgLibContImport->getByName( aLibName );
871                                 aElement >>= xDlgLibImport;
872 
873                                 if ( xDlgLibImport.is() )
874                                 {
875                                     // load library
876                                     if ( !xDlgLibContImport->isLibraryLoaded( aLibName ) )
877                                         xDlgLibContImport->loadLibrary( aLibName );
878 
879                                     // copy all dialogs
880                                     Sequence< OUString > aDlgNames = xDlgLibImport->getElementNames();
881                                     sal_Int32 nDlgCount = aDlgNames.getLength();
882                                     const OUString* pDlgNames = aDlgNames.getConstArray();
883                                     for ( sal_Int32 i = 0 ; i < nDlgCount ; i++ )
884                                     {
885                                         OUString aDlgName( pDlgNames[ i ] );
886                                         Any aElement_ = xDlgLibImport->getByName( aDlgName );
887                                         xDlgLib->insertByName( aDlgName, aElement_ );
888                                     }
889                                 }
890                             }
891                         }
892                     }
893 
894                     // insert listbox entry
895                     ImpInsertLibEntry( aLibName, m_xLibBox->n_children() );
896                     m_xLibBox->set_cursor( m_xLibBox->find_text(aLibName) );
897                     bChanges = true;
898                 }
899             }
900 
901             if ( bChanges )
902                 MarkDocumentModified( m_aCurDocument );
903         });
904 }
905 
Export()906 void LibPage::Export()
907 {
908     std::unique_ptr<weld::TreeIter> xCurEntry(m_xLibBox->make_iterator());
909     if (!m_xLibBox->get_cursor(xCurEntry.get()))
910         return;
911     OUString aLibName(m_xLibBox->get_text(*xCurEntry, 0));
912 
913     // Password verification
914     Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
915 
916     if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && !xModLibContainer->isLibraryLoaded( aLibName ) )
917     {
918         bool bOK = true;
919 
920         // check password
921         Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
922         if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( aLibName ) && !xPasswd->isLibraryPasswordVerified( aLibName ) )
923         {
924             OUString aPassword;
925             bOK = QueryPassword(m_pDialog->getDialog(), xModLibContainer, aLibName, aPassword);
926         }
927         if ( !bOK )
928             return;
929     }
930 
931     std::unique_ptr<ExportDialog> xNewDlg(new ExportDialog(m_pDialog->getDialog()));
932     if (xNewDlg->run() == RET_OK)
933     {
934         try
935         {
936             bool bExportAsPackage = xNewDlg->isExportAsPackage();
937             //tdf#112063 ensure closing xNewDlg is not selected as
938             //parent of file dialog from ExportAs...
939             xNewDlg.reset();
940             if (bExportAsPackage)
941                 ExportAsPackage( aLibName );
942             else
943                 ExportAsBasic( aLibName );
944         }
945         catch(const util::VetoException& ) // user canceled operation
946         {
947         }
948     }
949 }
950 
implExportLib(const OUString & aLibName,const OUString & aTargetURL,const Reference<task::XInteractionHandler> & Handler)951 void LibPage::implExportLib( const OUString& aLibName, const OUString& aTargetURL,
952     const Reference< task::XInteractionHandler >& Handler )
953 {
954     Reference< script::XLibraryContainerExport > xModLibContainerExport
955         ( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
956     Reference< script::XLibraryContainerExport > xDlgLibContainerExport
957         ( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY );
958     if ( xModLibContainerExport.is() )
959         xModLibContainerExport->exportLibrary( aLibName, aTargetURL, Handler );
960 
961     if (!xDlgLibContainerExport.is())
962         return;
963     Reference<container::XNameAccess> xNameAcc(xDlgLibContainerExport, UNO_QUERY);
964     if (!xNameAcc.is())
965         return;
966     if (!xNameAcc->hasByName(aLibName))
967         return;
968     xDlgLibContainerExport->exportLibrary(aLibName, aTargetURL, Handler);
969 }
970 
971 // Implementation XCommandEnvironment
972 
973 class OLibCommandEnvironment : public cppu::WeakImplHelper< XCommandEnvironment >
974 {
975     Reference< task::XInteractionHandler > mxInteraction;
976 
977 public:
OLibCommandEnvironment(const Reference<task::XInteractionHandler> & xInteraction)978     explicit OLibCommandEnvironment(const Reference<task::XInteractionHandler>& xInteraction)
979         : mxInteraction( xInteraction )
980     {}
981 
982     // Methods
983     virtual Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler() override;
984     virtual Reference< XProgressHandler > SAL_CALL getProgressHandler() override;
985 };
986 
getInteractionHandler()987 Reference< task::XInteractionHandler > OLibCommandEnvironment::getInteractionHandler()
988 {
989     return mxInteraction;
990 }
991 
getProgressHandler()992 Reference< XProgressHandler > OLibCommandEnvironment::getProgressHandler()
993 {
994     Reference< XProgressHandler > xRet;
995     return xRet;
996 }
997 
ExportAsPackage(const OUString & aLibName)998 void LibPage::ExportAsPackage( const OUString& aLibName )
999 {
1000     // file open dialog
1001     sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, FileDialogFlags::NONE, m_pDialog->getDialog());
1002     const Reference <XFilePicker3>& xFP = aDlg.GetFilePicker();
1003 
1004     Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1005     Reference< task::XInteractionHandler2 > xHandler( task::InteractionHandler::createWithParent(xContext, nullptr) );
1006     Reference< XSimpleFileAccess3 > xSFA = SimpleFileAccess::create(xContext);
1007 
1008     xFP->setTitle(IDEResId(RID_STR_EXPORTPACKAGE));
1009 
1010     // filter
1011     OUString aTitle(IDEResId(RID_STR_PACKAGE_BUNDLE));
1012     OUString aFilter = "*.oxt" ;       // library files
1013     xFP->appendFilter( aTitle, aFilter );
1014 
1015     // set display directory and filter
1016     OUString aPath = GetExtraData()->GetAddLibPath();
1017     if ( !aPath.isEmpty() )
1018     {
1019         xFP->setDisplayDirectory( aPath );
1020     }
1021     else
1022     {
1023         // macro path from configuration management
1024         xFP->setDisplayDirectory( SvtPathOptions().GetWorkPath() );
1025     }
1026     xFP->setCurrentFilter( aTitle );
1027 
1028     if ( xFP->execute() == RET_OK )
1029     {
1030         GetExtraData()->SetAddLibPath(xFP->getDisplayDirectory());
1031 
1032         Sequence< OUString > aFiles = xFP->getSelectedFiles();
1033         INetURLObject aURL( aFiles[0] );
1034         if( aURL.getExtension().isEmpty() )
1035             aURL.setExtension( "oxt" );
1036 
1037         OUString aPackageURL( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1038 
1039         OUString aTmpPath = SvtPathOptions().GetTempPath();
1040         INetURLObject aInetObj( aTmpPath );
1041         aInetObj.insertName( aLibName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1042         OUString aSourcePath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1043         if( xSFA->exists( aSourcePath ) )
1044             xSFA->kill( aSourcePath );
1045         Reference< task::XInteractionHandler > xDummyHandler( new DummyInteractionHandler( xHandler ) );
1046         implExportLib( aLibName, aTmpPath, xDummyHandler );
1047 
1048         Reference< XCommandEnvironment > xCmdEnv = new OLibCommandEnvironment(xHandler);
1049 
1050         ::ucbhelper::Content sourceContent( aSourcePath, xCmdEnv, comphelper::getProcessComponentContext() );
1051 
1052         OUString destFolder = "vnd.sun.star.zip://" +
1053                               ::rtl::Uri::encode( aPackageURL,
1054                                                   rtl_UriCharClassRegName,
1055                                                   rtl_UriEncodeIgnoreEscapes,
1056                                                   RTL_TEXTENCODING_UTF8 ) +
1057                               "/";
1058 
1059         if( xSFA->exists( aPackageURL ) )
1060             xSFA->kill( aPackageURL );
1061 
1062         ::ucbhelper::Content destFolderContent( destFolder, xCmdEnv, comphelper::getProcessComponentContext() );
1063         destFolderContent.transferContent(
1064             sourceContent, ::ucbhelper::InsertOperation::Copy,
1065             OUString(), NameClash::OVERWRITE );
1066 
1067         INetURLObject aMetaInfInetObj( aTmpPath );
1068         aMetaInfInetObj.insertName( "META-INF",
1069             true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1070         OUString aMetaInfFolder = aMetaInfInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1071         if( xSFA->exists( aMetaInfFolder ) )
1072             xSFA->kill( aMetaInfFolder );
1073         xSFA->createFolder( aMetaInfFolder );
1074 
1075         std::vector< Sequence<beans::PropertyValue> > manifest;
1076         const OUString strMediaType = "MediaType" ;
1077         const OUString strFullPath = "FullPath" ;
1078         const OUString strBasicMediaType = "application/vnd.sun.star.basic-library" ;
1079 
1080         OUString fullPath = aLibName
1081                           + "/" ;
1082         auto attribs(::comphelper::InitPropertySequence({
1083             { strFullPath, Any(fullPath) },
1084             { strMediaType, Any(strBasicMediaType) }
1085         }));
1086         manifest.push_back( attribs );
1087 
1088         // write into pipe:
1089         Reference<packages::manifest::XManifestWriter> xManifestWriter = packages::manifest::ManifestWriter::create( xContext );
1090         Reference<io::XOutputStream> xPipe( io::Pipe::create( xContext ), UNO_QUERY_THROW );
1091         xManifestWriter->writeManifestSequence(
1092             xPipe, Sequence< Sequence<beans::PropertyValue> >(
1093                 manifest.data(), manifest.size() ) );
1094 
1095         aMetaInfInetObj.insertName( "manifest.xml",
1096             true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1097 
1098         // write buffered pipe data to content:
1099         ::ucbhelper::Content manifestContent( aMetaInfInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xCmdEnv, comphelper::getProcessComponentContext() );
1100         manifestContent.writeStream( Reference<io::XInputStream>( xPipe, UNO_QUERY_THROW ), true );
1101 
1102         ::ucbhelper::Content MetaInfContent( aMetaInfFolder, xCmdEnv, comphelper::getProcessComponentContext() );
1103         destFolderContent.transferContent(
1104             MetaInfContent, ::ucbhelper::InsertOperation::Copy,
1105             OUString(), NameClash::OVERWRITE );
1106 
1107         if( xSFA->exists( aSourcePath ) )
1108             xSFA->kill( aSourcePath );
1109         if( xSFA->exists( aMetaInfFolder ) )
1110             xSFA->kill( aMetaInfFolder );
1111     }
1112 }
1113 
ExportAsBasic(const OUString & aLibName)1114 void LibPage::ExportAsBasic( const OUString& aLibName )
1115 {
1116     // Folder picker
1117     Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1118     Reference< XFolderPicker2 > xFolderPicker = FolderPicker::create(xContext);
1119     Reference< task::XInteractionHandler2 > xHandler( task::InteractionHandler::createWithParent(xContext, nullptr) );
1120 
1121     xFolderPicker->setTitle(IDEResId(RID_STR_EXPORTBASIC));
1122 
1123     // set display directory and filter
1124     OUString aPath =GetExtraData()->GetAddLibPath();
1125     if( aPath.isEmpty() )
1126         aPath = SvtPathOptions().GetWorkPath();
1127 
1128     // INetURLObject aURL(m_sSavePath, INetProtocol::File);
1129     xFolderPicker->setDisplayDirectory( aPath );
1130     short nRet = xFolderPicker->execute();
1131     if( nRet == RET_OK )
1132     {
1133         OUString aTargetURL = xFolderPicker->getDirectory();
1134         GetExtraData()->SetAddLibPath(aTargetURL);
1135 
1136         Reference< task::XInteractionHandler > xDummyHandler( new DummyInteractionHandler( xHandler ) );
1137         implExportLib( aLibName, aTargetURL, xDummyHandler );
1138     }
1139 }
1140 
DeleteCurrent()1141 void LibPage::DeleteCurrent()
1142 {
1143     std::unique_ptr<weld::TreeIter> xCurEntry(m_xLibBox->make_iterator());
1144     if (!m_xLibBox->get_cursor(xCurEntry.get()))
1145         return;
1146     OUString aLibName(m_xLibBox->get_text(*xCurEntry, 0));
1147 
1148     // check, if library is link
1149     bool bIsLibraryLink = false;
1150     Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
1151     Reference< script::XLibraryContainer2 > xDlgLibContainer( m_aCurDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY );
1152     if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) && xModLibContainer->isLibraryLink( aLibName ) ) ||
1153          ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryLink( aLibName ) ) )
1154     {
1155         bIsLibraryLink = true;
1156     }
1157 
1158     if (QueryDelLib(aLibName, bIsLibraryLink, m_pDialog->getDialog()))
1159     {
1160         // inform BasicIDE
1161         SfxUnoAnyItem aDocItem( SID_BASICIDE_ARG_DOCUMENT_MODEL, Any( m_aCurDocument.getDocumentOrNull() ) );
1162         SfxStringItem aLibNameItem( SID_BASICIDE_ARG_LIBNAME, aLibName );
1163         if (SfxDispatcher* pDispatcher = GetDispatcher())
1164             pDispatcher->ExecuteList(SID_BASICIDE_LIBREMOVED,
1165                       SfxCallMode::SYNCHRON, { &aDocItem, &aLibNameItem });
1166 
1167         // remove library from module and dialog library containers
1168         if ( xModLibContainer.is() && xModLibContainer->hasByName( aLibName ) )
1169             xModLibContainer->removeLibrary( aLibName );
1170         if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) )
1171             xDlgLibContainer->removeLibrary( aLibName );
1172 
1173         m_xLibBox->remove(*xCurEntry);
1174         MarkDocumentModified( m_aCurDocument );
1175     }
1176 }
1177 
EndTabDialog()1178 void LibPage::EndTabDialog()
1179 {
1180     m_pDialog->response(RET_OK);
1181 }
1182 
FillListBox()1183 void LibPage::FillListBox()
1184 {
1185     InsertListBoxEntry( ScriptDocument::getApplicationScriptDocument(), LIBRARY_LOCATION_USER );
1186     InsertListBoxEntry( ScriptDocument::getApplicationScriptDocument(), LIBRARY_LOCATION_SHARE );
1187 
1188     ScriptDocuments aDocuments( ScriptDocument::getAllScriptDocuments( ScriptDocument::DocumentsSorted ) );
1189     for (auto const& doc : aDocuments)
1190     {
1191         InsertListBoxEntry( doc, LIBRARY_LOCATION_DOCUMENT );
1192     }
1193 }
1194 
InsertListBoxEntry(const ScriptDocument & rDocument,LibraryLocation eLocation)1195 void LibPage::InsertListBoxEntry( const ScriptDocument& rDocument, LibraryLocation eLocation )
1196 {
1197     OUString aEntryText(rDocument.getTitle(eLocation));
1198     OUString sId(OUString::number(reinterpret_cast<sal_Int64>(new DocumentEntry(rDocument, eLocation))));
1199     m_xBasicsBox->append(sId,  aEntryText);
1200 }
1201 
SetCurLib()1202 void LibPage::SetCurLib()
1203 {
1204     DocumentEntry* pEntry = reinterpret_cast<DocumentEntry*>(m_xBasicsBox->get_active_id().toInt64());
1205     if (pEntry)
1206     {
1207         const ScriptDocument& aDocument( pEntry->GetDocument() );
1208         DBG_ASSERT( aDocument.isAlive(), "LibPage::SetCurLib: no document, or document is dead!" );
1209         if ( !aDocument.isAlive() )
1210             return;
1211         LibraryLocation eLocation = pEntry->GetLocation();
1212         if ( aDocument != m_aCurDocument || eLocation != m_eCurLocation )
1213         {
1214             m_aCurDocument = aDocument;
1215             m_eCurLocation = eLocation;
1216             m_xLibBox->clear();
1217 
1218             // get a sorted list of library names
1219             Sequence< OUString > aLibNames = aDocument.getLibraryNames();
1220             sal_Int32 nLibCount = aLibNames.getLength();
1221             const OUString* pLibNames = aLibNames.getConstArray();
1222 
1223             int nEntry = 0;
1224             for (int i = 0 ; i < nLibCount; ++i)
1225             {
1226                 OUString aLibName(pLibNames[i]);
1227                 if (eLocation == aDocument.getLibraryLocation(aLibName))
1228                     ImpInsertLibEntry(aLibName, nEntry++);
1229             }
1230 
1231             int nEntry_ = FindEntry(*m_xLibBox, "Standard");
1232             if (nEntry_ == -1 && m_xLibBox->n_children())
1233                 nEntry_ = 0;
1234             m_xLibBox->set_cursor(nEntry_);
1235         }
1236     }
1237 }
1238 
ImpInsertLibEntry(const OUString & rLibName,sal_uLong nPos)1239 void LibPage::ImpInsertLibEntry( const OUString& rLibName, sal_uLong nPos )
1240 {
1241     // check, if library is password protected
1242     bool bProtected = false;
1243     Reference< script::XLibraryContainer2 > xModLibContainer( m_aCurDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
1244     if ( xModLibContainer.is() && xModLibContainer->hasByName( rLibName ) )
1245     {
1246         Reference< script::XLibraryContainerPassword > xPasswd( xModLibContainer, UNO_QUERY );
1247         if ( xPasswd.is() )
1248         {
1249             bProtected = xPasswd->isLibraryPasswordProtected( rLibName );
1250         }
1251     }
1252 
1253     m_xLibBox->insert_text(nPos, rLibName);
1254 
1255     if (bProtected)
1256         m_xLibBox->set_image(nPos, RID_BMP_LOCKED);
1257 
1258     // check, if library is link
1259     if ( xModLibContainer.is() && xModLibContainer->hasByName( rLibName ) && xModLibContainer->isLibraryLink( rLibName ) )
1260     {
1261         OUString aLinkURL = xModLibContainer->getLibraryLinkURL( rLibName );
1262         m_xLibBox->set_text(nPos, aLinkURL, 1);
1263     }
1264 }
1265 
1266 // Helper function
createLibImpl(weld::Window * pWin,const ScriptDocument & rDocument,weld::TreeView * pLibBox,SbTreeListBox * pBasicBox)1267 void createLibImpl(weld::Window* pWin, const ScriptDocument& rDocument,
1268                    weld::TreeView* pLibBox, SbTreeListBox* pBasicBox)
1269 {
1270     OSL_ENSURE( rDocument.isAlive(), "createLibImpl: invalid document!" );
1271     if ( !rDocument.isAlive() )
1272         return;
1273 
1274     // create library name
1275     OUString aLibName;
1276     bool bValid = false;
1277     sal_Int32 i = 1;
1278     while ( !bValid )
1279     {
1280         aLibName = "Library" + OUString::number( i );
1281         if ( !rDocument.hasLibrary( E_SCRIPTS, aLibName ) && !rDocument.hasLibrary( E_DIALOGS, aLibName ) )
1282             bValid = true;
1283         i++;
1284     }
1285 
1286     NewObjectDialog aNewDlg(pWin, ObjectMode::Library);
1287     aNewDlg.SetObjectName(aLibName);
1288 
1289     if (aNewDlg.run())
1290     {
1291         if (!aNewDlg.GetObjectName().isEmpty())
1292             aLibName = aNewDlg.GetObjectName();
1293 
1294         if ( aLibName.getLength() > 30 )
1295         {
1296             std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pWin,
1297                                                            VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_LIBNAMETOLONG)));
1298             xErrorBox->run();
1299         }
1300         else if ( !IsValidSbxName( aLibName ) )
1301         {
1302             std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pWin,
1303                                                            VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME)));
1304             xErrorBox->run();
1305         }
1306         else if ( rDocument.hasLibrary( E_SCRIPTS, aLibName ) || rDocument.hasLibrary( E_DIALOGS, aLibName ) )
1307         {
1308             std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pWin,
1309                                                            VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_SBXNAMEALLREADYUSED2)));
1310             xErrorBox->run();
1311         }
1312         else
1313         {
1314             try
1315             {
1316                 // create module and dialog library
1317                 Reference< container::XNameContainer > xModLib( rDocument.getOrCreateLibrary( E_SCRIPTS, aLibName ) );
1318                 Reference< container::XNameContainer > xDlgLib( rDocument.getOrCreateLibrary( E_DIALOGS, aLibName ) );
1319 
1320                 if( pLibBox )
1321                 {
1322                     pLibBox->append_text(aLibName);
1323                     pLibBox->set_cursor(pLibBox->find_text(aLibName));
1324                 }
1325 
1326                 // create a module
1327                 OUString aModName = rDocument.createObjectName( E_SCRIPTS, aLibName );
1328                 OUString sModuleCode;
1329                 if ( !rDocument.createModule( aLibName, aModName, true, sModuleCode ) )
1330                     throw Exception("could not create module " + aModName, nullptr);
1331 
1332                 SbxItem aSbxItem( SID_BASICIDE_ARG_SBX, rDocument, aLibName, aModName, TYPE_MODULE );
1333                 if (SfxDispatcher* pDispatcher = GetDispatcher())
1334                     pDispatcher->ExecuteList(SID_BASICIDE_SBXINSERTED,
1335                                           SfxCallMode::SYNCHRON, { &aSbxItem });
1336 
1337                 if( pBasicBox )
1338                 {
1339                     std::unique_ptr<weld::TreeIter> xIter(pBasicBox->make_iterator(nullptr));
1340                     bool bValidIter = pBasicBox->get_cursor(xIter.get());
1341                     std::unique_ptr<weld::TreeIter> xRootEntry(pBasicBox->make_iterator(xIter.get()));
1342                     while (bValidIter)
1343                     {
1344                         pBasicBox->copy_iterator(*xIter, *xRootEntry);
1345                         bValidIter = pBasicBox->iter_parent(*xIter);
1346                     }
1347 
1348                     BrowseMode nMode = pBasicBox->GetMode();
1349                     bool bDlgMode = ( nMode & BrowseMode::Dialogs ) && !( nMode & BrowseMode::Modules );
1350                     const OUString sId = bDlgMode ? OUStringLiteral(RID_BMP_DLGLIB) : OUStringLiteral(RID_BMP_MODLIB);
1351                     pBasicBox->AddEntry(aLibName, sId, xRootEntry.get(), false, std::make_unique<Entry>(OBJ_TYPE_LIBRARY));
1352                     pBasicBox->AddEntry(aModName, RID_BMP_MODULE, xRootEntry.get(), false, std::make_unique<Entry>(OBJ_TYPE_MODULE));
1353                     pBasicBox->set_cursor(*xRootEntry);
1354                     pBasicBox->select(*xRootEntry);
1355                 }
1356             }
1357             catch (const uno::Exception& )
1358             {
1359                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1360             }
1361         }
1362     }
1363 }
1364 
1365 } // namespace basctl
1366 
1367 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1368