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