001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.importexport;
029
030import org.opencms.configuration.CmsParameterConfiguration;
031import org.opencms.file.CmsDataAccessException;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsProperty;
034import org.opencms.file.CmsPropertyDefinition;
035import org.opencms.file.CmsResource;
036import org.opencms.file.types.CmsResourceTypeFolder;
037import org.opencms.file.types.CmsResourceTypePlain;
038import org.opencms.file.types.CmsResourceTypePointer;
039import org.opencms.file.types.CmsResourceTypeXmlPage;
040import org.opencms.file.types.I_CmsResourceType;
041import org.opencms.i18n.CmsMessageContainer;
042import org.opencms.main.CmsException;
043import org.opencms.main.CmsLog;
044import org.opencms.main.OpenCms;
045import org.opencms.report.I_CmsReport;
046import org.opencms.security.CmsAccessControlEntry;
047import org.opencms.security.CmsRole;
048import org.opencms.security.I_CmsPasswordHandler;
049import org.opencms.security.I_CmsPrincipal;
050import org.opencms.util.CmsUUID;
051import org.opencms.xml.CmsXmlEntityResolver;
052import org.opencms.xml.CmsXmlException;
053import org.opencms.xml.CmsXmlUtils;
054import org.opencms.xml.page.CmsXmlPage;
055
056import java.io.File;
057import java.io.IOException;
058import java.util.ArrayList;
059import java.util.Collections;
060import java.util.HashMap;
061import java.util.List;
062import java.util.Map;
063import java.util.zip.ZipFile;
064
065import org.apache.commons.logging.Log;
066
067import org.dom4j.Document;
068import org.dom4j.Element;
069import org.dom4j.Node;
070
071/**
072 * Implementation of the OpenCms Import Interface ({@link org.opencms.importexport.I_CmsImport}) for
073 * the import version 3.<p>
074 *
075 * This import format was used in OpenCms 5.1.2 - 5.1.6.<p>
076 *
077 * @since 6.0.0
078 *
079 * @see org.opencms.importexport.A_CmsImport
080 *
081 * @deprecated this import class is no longer in use and should only be used to import old export files
082 */
083@Deprecated
084public class CmsImportVersion3 extends A_CmsImport {
085
086    /** The version number of this import implementation.<p> */
087    private static final int IMPORT_VERSION = 3;
088
089    /** The log object for this class. */
090    private static final Log LOG = CmsLog.getLog(CmsImportVersion3.class);
091
092    /**
093     * Creates a new CmsImportVerion3 object.<p>
094     */
095    public CmsImportVersion3() {
096
097        m_convertToXmlPage = true;
098    }
099
100    /**
101     * @see org.opencms.importexport.I_CmsImport#getVersion()
102     * @return the version number of this import implementation
103     */
104    public int getVersion() {
105
106        return CmsImportVersion3.IMPORT_VERSION;
107    }
108
109    /**
110     * @see org.opencms.importexport.I_CmsImport#importData(CmsObject, I_CmsReport, CmsImportParameters)
111     */
112    public void importData(CmsObject cms, I_CmsReport report, CmsImportParameters params)
113    throws CmsImportExportException, CmsXmlException {
114
115        // initialize the import
116        initialize();
117        m_cms = cms;
118        m_importPath = params.getDestinationPath();
119        m_report = report;
120
121        m_linkStorage = new HashMap<String, String>();
122        m_linkPropertyStorage = new HashMap<String, List<CmsProperty>>();
123        CmsImportHelper helper = new CmsImportHelper(params);
124        try {
125            helper.openFile();
126            m_importResource = helper.getFolder();
127            m_importZip = helper.getZipFile();
128            m_docXml = CmsXmlUtils.unmarshalHelper(
129                helper.getFileBytes(CmsImportExportManager.EXPORT_MANIFEST),
130                new CmsXmlEntityResolver(null));
131            // first import the user information
132            if (OpenCms.getRoleManager().hasRole(m_cms, CmsRole.ACCOUNT_MANAGER)) {
133                importGroups();
134                importUsers();
135            }
136            // now import the VFS resources
137            importAllResources();
138            convertPointerToSiblings();
139        } catch (IOException ioe) {
140            CmsMessageContainer msg = Messages.get().container(
141                Messages.ERR_IMPORTEXPORT_ERROR_READING_FILE_1,
142                CmsImportExportManager.EXPORT_MANIFEST);
143            if (LOG.isErrorEnabled()) {
144                LOG.error(msg.key(), ioe);
145            }
146            throw new CmsImportExportException(msg, ioe);
147        } finally {
148            helper.closeFile();
149            cleanUp();
150        }
151    }
152
153    /**
154     * @see org.opencms.importexport.I_CmsImport#importResources(org.opencms.file.CmsObject, java.lang.String, org.opencms.report.I_CmsReport, java.io.File, java.util.zip.ZipFile, org.dom4j.Document)
155     *
156     * @deprecated use {@link #importData(CmsObject, I_CmsReport, CmsImportParameters)} instead
157     */
158    @Deprecated
159    public void importResources(
160        CmsObject cms,
161        String importPath,
162        I_CmsReport report,
163        File importResource,
164        ZipFile importZip,
165        Document docXml)
166    throws CmsImportExportException {
167
168        CmsImportParameters params = new CmsImportParameters(
169            importResource != null ? importResource.getAbsolutePath() : importZip.getName(),
170            importPath,
171            true);
172
173        try {
174            importData(cms, report, params);
175        } catch (CmsXmlException e) {
176            throw new CmsImportExportException(e.getMessageContainer(), e);
177        }
178    }
179
180    /**
181     * @see org.opencms.importexport.A_CmsImport#importUser(String, String, String, String, String, String, long, Map, List)
182     */
183    @Override
184    protected void importUser(
185        String name,
186        String flags,
187        String password,
188        String firstname,
189        String lastname,
190        String email,
191        long dateCreated,
192        Map<String, Object> userInfo,
193        List<String> userGroups)
194    throws CmsImportExportException {
195
196        boolean convert = false;
197
198        CmsParameterConfiguration config = OpenCms.getPasswordHandler().getConfiguration();
199        if ((config != null) && config.containsKey(I_CmsPasswordHandler.CONVERT_DIGEST_ENCODING)) {
200            convert = config.getBoolean(I_CmsPasswordHandler.CONVERT_DIGEST_ENCODING, false);
201        }
202
203        if (convert) {
204            password = convertDigestEncoding(password);
205        }
206
207        super.importUser(name, flags, password, firstname, lastname, email, dateCreated, userInfo, userGroups);
208    }
209
210    /**
211     * Imports the resources and writes them to the cms.<p>
212     *
213     * @throws CmsImportExportException if something goes wrong
214     */
215    private void importAllResources() throws CmsImportExportException {
216
217        String source, destination, type, uuidresource, userlastmodified, usercreated, flags, timestamp;
218        long datelastmodified, datecreated;
219
220        List<Node> fileNodes;
221        List<Node> acentryNodes;
222        Element currentElement, currentEntry;
223        List<CmsProperty> properties = null;
224
225        // get list of unwanted properties
226        List<String> deleteProperties = OpenCms.getImportExportManager().getIgnoredProperties();
227        if (deleteProperties == null) {
228            deleteProperties = new ArrayList<String>();
229        }
230        // get list of immutable resources
231        List<String> immutableResources = OpenCms.getImportExportManager().getImmutableResources();
232        if (immutableResources == null) {
233            immutableResources = Collections.EMPTY_LIST;
234        }
235        if (LOG.isDebugEnabled()) {
236            LOG.debug(
237                Messages.get().getBundle().key(
238                    Messages.LOG_IMPORTEXPORT_IMMUTABLE_RESOURCES_SIZE_1,
239                    Integer.toString(immutableResources.size())));
240        }
241        // get the wanted page type for imported pages
242        m_convertToXmlPage = OpenCms.getImportExportManager().convertToXmlPage();
243
244        try {
245            // get all file-nodes
246            fileNodes = m_docXml.selectNodes("//" + A_CmsImport.N_FILE);
247
248            int importSize = fileNodes.size();
249            // walk through all files in manifest
250            for (int i = 0; i < fileNodes.size(); i++) {
251                m_report.print(
252                    org.opencms.report.Messages.get().container(
253                        org.opencms.report.Messages.RPT_SUCCESSION_2,
254                        String.valueOf(i + 1),
255                        String.valueOf(importSize)));
256                currentElement = (Element)fileNodes.get(i);
257                // get all information for a file-import
258                // <source>
259                source = getChildElementTextValue(currentElement, A_CmsImport.N_SOURCE);
260                // <destintion>
261                destination = getChildElementTextValue(currentElement, A_CmsImport.N_DESTINATION);
262                // <type>
263                type = getChildElementTextValue(currentElement, A_CmsImport.N_TYPE);
264                // <uuidstructure>
265                //uuidstructure = CmsImport.getChildElementTextValue(
266                //    currentElement,
267                //    CmsImportExportManager.N_UUIDSTRUCTURE);
268                // <uuidresource>
269                uuidresource = getChildElementTextValue(currentElement, A_CmsImport.N_UUIDRESOURCE);
270                // <datelastmodified>
271                timestamp = getChildElementTextValue(currentElement, A_CmsImport.N_DATELASTMODIFIED);
272                if (timestamp != null) {
273                    datelastmodified = Long.parseLong(timestamp);
274                } else {
275                    datelastmodified = System.currentTimeMillis();
276                }
277                // <userlastmodified>
278                userlastmodified = getChildElementTextValue(currentElement, A_CmsImport.N_USERLASTMODIFIED);
279                // <datecreated>
280                timestamp = getChildElementTextValue(currentElement, A_CmsImport.N_DATECREATED);
281                if (timestamp != null) {
282                    datecreated = Long.parseLong(timestamp);
283                } else {
284                    datecreated = System.currentTimeMillis();
285                }
286                // <usercreated>
287                usercreated = getChildElementTextValue(currentElement, A_CmsImport.N_USERCREATED);
288                // <flags>
289                flags = getChildElementTextValue(currentElement, A_CmsImport.N_FLAGS);
290
291                String translatedName = m_cms.getRequestContext().addSiteRoot(m_importPath + destination);
292                if (CmsResourceTypeFolder.RESOURCE_TYPE_NAME.equals(type)) {
293                    translatedName += "/";
294                }
295                // translate the name during import
296                translatedName = m_cms.getRequestContext().getDirectoryTranslator().translateResource(translatedName);
297                // check if this resource is immutable
298                boolean resourceNotImmutable = checkImmutable(translatedName, immutableResources);
299                translatedName = m_cms.getRequestContext().removeSiteRoot(translatedName);
300                // if the resource is not immutable and not on the exclude list, import it
301                if (resourceNotImmutable) {
302                    // print out the information to the report
303                    m_report.print(Messages.get().container(Messages.RPT_IMPORTING_0), I_CmsReport.FORMAT_NOTE);
304                    m_report.print(
305                        org.opencms.report.Messages.get().container(
306                            org.opencms.report.Messages.RPT_ARGUMENT_1,
307                            translatedName));
308                    //m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0));
309                    // get all properties
310                    properties = readPropertiesFromManifest(currentElement, deleteProperties);
311
312                    // import the resource
313                    CmsResource res = importResource(
314                        source,
315                        destination,
316                        type,
317                        uuidresource,
318                        datelastmodified,
319                        userlastmodified,
320                        datecreated,
321                        usercreated,
322                        flags,
323                        properties);
324
325                    List<CmsAccessControlEntry> aceList = new ArrayList<CmsAccessControlEntry>();
326                    if (res != null) {
327                        // write all imported access control entries for this file
328                        acentryNodes = currentElement.selectNodes("*/" + A_CmsImport.N_ACCESSCONTROL_ENTRY);
329                        // collect all access control entries
330                        for (int j = 0; j < acentryNodes.size(); j++) {
331                            currentEntry = (Element)acentryNodes.get(j);
332                            // get the data of the access control entry
333                            String id = getChildElementTextValue(currentEntry, A_CmsImport.N_ACCESSCONTROL_PRINCIPAL);
334                            String acflags = getChildElementTextValue(currentEntry, A_CmsImport.N_FLAGS);
335                            String allowed = getChildElementTextValue(
336                                currentEntry,
337                                A_CmsImport.N_ACCESSCONTROL_PERMISSIONSET
338                                    + "/"
339                                    + A_CmsImport.N_ACCESSCONTROL_ALLOWEDPERMISSIONS);
340                            String denied = getChildElementTextValue(
341                                currentEntry,
342                                A_CmsImport.N_ACCESSCONTROL_PERMISSIONSET
343                                    + "/"
344                                    + A_CmsImport.N_ACCESSCONTROL_DENIEDPERMISSIONS);
345
346                            // get the correct principal
347                            try {
348                                String principalId = new CmsUUID().toString();
349                                String principal = id.substring(id.indexOf('.') + 1, id.length());
350
351                                if (id.startsWith(I_CmsPrincipal.PRINCIPAL_GROUP)) {
352                                    principal = OpenCms.getImportExportManager().translateGroup(principal);
353                                    principalId = m_cms.readGroup(principal).getId().toString();
354                                } else {
355                                    principal = OpenCms.getImportExportManager().translateUser(principal);
356                                    principalId = m_cms.readUser(principal).getId().toString();
357                                }
358
359                                // add the entry to the list
360                                aceList.add(getImportAccessControlEntry(res, principalId, allowed, denied, acflags));
361                            } catch (CmsDataAccessException e) {
362                                // user or group not found, so do not import the ace
363                            }
364                        }
365                        importAccessControlEntries(res, aceList);
366
367                    } else {
368                        // resource import failed, since no CmsResource was created
369                        m_report.print(Messages.get().container(Messages.RPT_SKIPPING_0), I_CmsReport.FORMAT_NOTE);
370                        m_report.println(
371                            org.opencms.report.Messages.get().container(
372                                org.opencms.report.Messages.RPT_ARGUMENT_1,
373                                translatedName));
374                    }
375                } else {
376                    // skip the file import, just print out the information to the report
377                    m_report.print(Messages.get().container(Messages.RPT_SKIPPING_0), I_CmsReport.FORMAT_NOTE);
378                    m_report.println(
379                        org.opencms.report.Messages.get().container(
380                            org.opencms.report.Messages.RPT_ARGUMENT_1,
381                            translatedName));
382                }
383            }
384
385        } catch (Exception e) {
386            m_report.println(e);
387            m_report.addError(e);
388
389            CmsMessageContainer message = Messages.get().container(
390                Messages.ERR_IMPORTEXPORT_ERROR_IMPORTING_RESOURCES_0);
391            if (LOG.isDebugEnabled()) {
392                LOG.debug(message.key(), e);
393            }
394            throw new CmsImportExportException(message, e);
395        }
396
397    }
398
399    /**
400     * Imports a resource (file or folder) into the cms.<p>
401     *
402     * @param source the path to the source-file
403     * @param destination the path to the destination-file in the cms
404     * @param type the resource-type of the file
405     * @param uuidresource  the resource uuid of the resource
406     * @param datelastmodified the last modification date of the resource
407     * @param userlastmodified the user who made the last modifications to the resource
408     * @param datecreated the creation date of the resource
409     * @param usercreated the user who created
410     * @param flags the flags of the resource
411     * @param properties a list with properties for this resource
412     *
413     * @return imported resource
414     */
415    private CmsResource importResource(
416        String source,
417        String destination,
418        String type,
419        String uuidresource,
420        long datelastmodified,
421        String userlastmodified,
422        long datecreated,
423        String usercreated,
424        String flags,
425        List<CmsProperty> properties) {
426
427        byte[] content = null;
428        CmsResource result = null;
429
430        try {
431
432            // get the file content
433            if (source != null) {
434                content = getFileBytes(source);
435            }
436            int size = 0;
437            if (content != null) {
438                size = content.length;
439            }
440
441            // get all required information to create a CmsResource
442            I_CmsResourceType resType;
443
444            // get UUIDs for the user
445            CmsUUID newUserlastmodified;
446            CmsUUID newUsercreated;
447            // check if user created and user lastmodified are valid users in this system.
448            // if not, use the current user
449            try {
450                newUserlastmodified = m_cms.readUser(userlastmodified).getId();
451            } catch (CmsException e) {
452                newUserlastmodified = m_cms.getRequestContext().getCurrentUser().getId();
453                // datelastmodified = System.currentTimeMillis();
454            }
455
456            try {
457                newUsercreated = m_cms.readUser(usercreated).getId();
458            } catch (CmsException e) {
459                newUsercreated = m_cms.getRequestContext().getCurrentUser().getId();
460                // datecreated = System.currentTimeMillis();
461            }
462
463            // convert to xml page if wanted
464            if (m_convertToXmlPage && (type.equals(RESOURCE_TYPE_NEWPAGE_NAME))) {
465
466                if (content != null) {
467
468                    //get the encoding
469                    String encoding = null;
470                    encoding = CmsProperty.get(CmsPropertyDefinition.PROPERTY_CONTENT_ENCODING, properties).getValue();
471                    if (encoding == null) {
472                        encoding = OpenCms.getSystemInfo().getDefaultEncoding();
473                    }
474
475                    CmsXmlPage xmlPage = CmsXmlPageConverter.convertToXmlPage(
476                        m_cms,
477                        content,
478                        getLocale(destination, properties),
479                        encoding);
480
481                    content = xmlPage.marshal();
482                }
483                resType = OpenCms.getResourceManager().getResourceType(CmsResourceTypeXmlPage.getStaticTypeId());
484            } else if (type.equals(RESOURCE_TYPE_LINK_NAME)) {
485                resType = OpenCms.getResourceManager().getResourceType(CmsResourceTypePointer.getStaticTypeId());
486            } else if (type.equals(RESOURCE_TYPE_LEGACY_PAGE_NAME)) {
487                resType = OpenCms.getResourceManager().getResourceType(CmsResourceTypePlain.getStaticTypeId());
488            } else {
489                resType = OpenCms.getResourceManager().getResourceType(type);
490            }
491
492            // get UUIDs for the resource and content
493            CmsUUID newUuidresource = null;
494            if ((uuidresource != null) && (!resType.isFolder())) {
495                // create a UUID from the provided string
496                newUuidresource = new CmsUUID(uuidresource);
497            } else {
498                // folders get always a new resource record UUID
499                newUuidresource = new CmsUUID();
500            }
501
502            // create a new CmsResource
503            CmsResource resource = new CmsResource(
504                new CmsUUID(), // structure ID is always a new UUID
505                newUuidresource,
506                destination,
507                resType.getTypeId(),
508                resType.isFolder(),
509                Integer.valueOf(flags).intValue(),
510                m_cms.getRequestContext().getCurrentProject().getUuid(),
511                CmsResource.STATE_NEW,
512                datecreated,
513                newUsercreated,
514                datelastmodified,
515                newUserlastmodified,
516                CmsResource.DATE_RELEASED_DEFAULT,
517                CmsResource.DATE_EXPIRED_DEFAULT,
518                1,
519                size,
520                System.currentTimeMillis(),
521                0);
522
523            if (type.equals(RESOURCE_TYPE_LINK_NAME)) {
524                // store links for later conversion
525                m_report.print(Messages.get().container(Messages.RPT_STORING_LINK_0), I_CmsReport.FORMAT_NOTE);
526                m_linkStorage.put(m_importPath + destination, new String(content));
527                m_linkPropertyStorage.put(m_importPath + destination, properties);
528                result = resource;
529            } else {
530                // import this resource in the VFS
531                result = m_cms.importResource(destination, resource, content, properties);
532            }
533
534            if (result != null) {
535                m_report.println(
536                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
537                    I_CmsReport.FORMAT_OK);
538            }
539        } catch (Exception exc) {
540            // an error while importing the file
541            m_report.println(exc);
542            m_report.addError(exc);
543
544            try {
545                // Sleep some time after an error so that the report output has a chance to keep up
546                Thread.sleep(1000);
547            } catch (Exception e) {
548                //
549            }
550        }
551
552        return result;
553    }
554}