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