[opencms-dev] some bug fixes and enhancements for OpenCms 5.0.1
Vincent Hanniet
vhanniet at free.fr
Wed Jul 7 16:52:01 CEST 2004
Very good idea. Thank you Sven from Getit !
Vincent
Sven Bonorden wrote:
> Hi all,
>
> during our work with OpenCms 5.0.1 we had to change many classes of the
> OpenCms core itself.
> Our main work is commercial and very customer-specific, but the core
> changes are of course Open Source.
> I collected the bug fixes and enhancements so anyone having similar
> problems can use our solutions.
>
> Maybe some of our modifications could also be added to version 6 but I
> did not check if they work in the current CVS head as we only used 5.0.1.
> That's why I did not add the complete java files or patch files so the
> core developers can decide what may be necessary.
>
> Bug fixes (details see attached file, some of them are already in Bugzilla)
> - When restoring an old version of a resource, the properties of this
> version are not restored (#361)
> - Log channels in property file have wrong names and so they are never
> used.
> - When a folder is copied and the destination folder already exists, the
> copying fails (#362)
> - You cannot add new resource types if their classes are in a module
> - Moving or renaming a folder resource does not move the /system/bodies
> folder (#363)
> - Cms always sents Mails in charset ISO8859-1
> - Link substitution ignores urls in <input src="..."> and <form
> action="...">
> - The source editor cannot display special characters from Eastern Europe
> - Some German spelling errors, mainly to fix different spellings of
> "Ressource"
> - CmsRequestContext.getSession fails with NullPointerException if no
> request is available
> - Scheduler does not start jobs if the minute is 0 (#74)
> - when creating a resource, the property values (i.e. title) are not
> encoded correctly on some systems
> - It is impossible to disable the scheduler when creating a new CmsObject
> - In CmsResourceBroker some methods change the file-state after saving
> the file. That does not make sense.
> - If copying a resource, the owner and group are also copied from the
> source.
> - CmsResourceBroker.readAllFileHeadersForHist throws a CmsException if
> the resource has been deleted (#348)
> - Two different backup versions of a resource are considered equal
> - Trying to send a mail from a scheduled job fails with
> NullPointerException (#364)
> - Access checks for read and visible return a wrong result if the user
> has these privileges via his group (#365)
>
> Enhancements (details see attached file)
> - Change the group for a resource recursively from CmsShell
> - Methods to access a project with a specific name from CmsShell
> - Methods to read properties from a backup version for a resource
> - CmsSetupUtils cannot read Property values containing a comma
> - Functionality for users to be logged in without a password
> - Workplace Popup for folder tree always starts with root folder
> - You cannot get a specific project by its name
> - write a property if the property definition does not exist
> - find a folder with a specific name searching only through a part of VFS
> - find all resources in a folder that have been published after a
> specific date
> - get the resource type of a deleted resource
> - folder tree popup to show not only the name, but also the title
>
> Kind regards,
> Sven
>
>
> ------------------------------------------------------------------------
>
> Bugfixes for OpenCms 5.0.1:
> -------------------------------
>
> This file lists bugfixes made by GETIT GmbH for productional use of OpenCms 5.0.1.
>
> ---------------------------------------------------------------------------------------------------
>
> Bug 361:
> When restoring an old version of a resource, the properties of this version are not restored.
>
> com.opencms.file.genericSql.CmsDbAccess:
> - new method:
> /**
> * Returns a list of all history properties of a file or folder.<p>
> *
> * @param resourceId the id of the resource
> * @param resource the resource to read the properties from
> * @param resourceType the type of the resource
> *
> * @return a Map of Strings representing the properties of the resource
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public HashMap readPropertiesForHist(CmsResource resource, int resourceType)
> throws CmsException {
>
> HashMap returnValue = new HashMap();
> ResultSet result = null;
> PreparedStatement statement = null;
> Connection con = null;
> String usedPool;
> int resourceId = resource.getResourceId();
> //int onlineProject = getOnlineProject(projectId).getId();
> usedPool = m_poolNameBackup;
> try {
> con = DriverManager.getConnection(usedPool);
> // create project
> statement = con.prepareStatement(m_cq.get("C_PROPERTIES_READALL_BACKUP"));
> statement.setInt(1, resourceId);
> statement.setInt(2, resourceType);
> result = statement.executeQuery();
> while(result.next()) {
> returnValue.put(result.getString(m_cq.get("C_PROPERTYDEF_NAME")),
> result.getString(m_cq.get("C_PROPERTY_VALUE")));
> }
> } catch( SQLException exc ) {
> throw new CmsException("[" + this.getClass().getName() + "] " + exc.getMessage(),
> CmsException.C_SQL_ERROR, exc);
> } finally {
> // close all db-resources
> if(result != null) {
> try {
> result.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(statement != null) {
> try {
> statement.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(con != null) {
> try {
> con.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> }
> return(returnValue);
> }
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - new constant:
> protected static final String C_CACHE_ALL_BACKUP_PROPERTIES = "__CACHE_ALL_BACKUP_PROPERTIES__";
>
> - new method:
> /**
> * Looks up all properties for a resource with optional direcory upward cascading.<p>
> *
> *
> * @param currentUser the current user
> * @param currentProject the current project of the user
> * @param resource the resource to look up the property for
> * @param siteRoot the current site root
> * @param search if <code>true</code>, the properties will also be looked up on all parent folders
> * and the results will be merged, if <code>false</code> not (ie. normal property lookup)
> * @return Map of Strings representing all properties of the resource
> * @throws CmsException in case there where problems reading the properties
> */
> public Map readPropertiesForHist(CmsUser currentUser, CmsProject currentProject, String resource, String siteRoot, boolean search, int version_id)
> throws CmsException {
> // read the resource from history
> CmsResource res = readFileForHist (currentUser, currentProject, version_id,resource);
>
> search = search && (siteRoot != null);
> // check if we have the result already cached
> HashMap value = null;
>
> String cacheKey = getCacheKey(C_CACHE_ALL_BACKUP_PROPERTIES + search+version_id, null, new CmsProject(currentProject.getId(), -1), res.getResourceName());
> value = (HashMap)m_propertyCache.get(cacheKey);
>
> if (value == null) {
> // result not cached, let's look it up in the DB
> if (search) {
> boolean cont;
> siteRoot += "/";
> value = new HashMap();
> HashMap parentValue;
> do {
> parentValue = (HashMap)readProperties(currentUser, currentProject, resource, siteRoot, false);
> parentValue.putAll(value);
> value.clear();
> value.putAll(parentValue);
> resource = CmsResource.getParent(resource);
> cont = (! siteRoot.equals(resource));
> } while (cont);
> } else {
> value = m_dbAccess.readPropertiesForHist(res, res.getType());
> }
> // store the result in the cache
> m_propertyCache.put(cacheKey, value);
> }
> return (Map)value.clone();
> }
>
> - change method restoreResource:
> old version:
> writeFile(currentUser, currentProject, newFile);
>
> new version:
> writeFile(currentUser, currentProject, newFile);
> deleteAllProperties(currentUser,currentProject,newFile.getResourceName());
> Map oldProperties = readPropertiesForHist(currentUser,currentProject,newFile.getResourceName(),null,false,versionId);
> writeProperties(currentUser,currentProject,newFile.getResourceName(),oldProperties);
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * Looks up all properties from a backup resource with optional directory upward cascading.<p>
> *
> * <b>Security:</b>
> * Only a user is granted who has the right to read the resource.
> *
> * @param currentUser the current user
> * @param currentProject the current project of the user
> * @param resource the resource to look up the property for
> * @param siteroot the site root where to stop the cascading
> * @param search if <code>true</code>, the properties will also be looked up on all parent folders
> * and the results will be merged, if <code>false</code> not (ie. normal property lookup)
> * @param versionId the version id containing the defined properties
> * @return Map of Strings representing all properties of the resource
> * @throws CmsException in case there where problems reading the properties
> */
> public Map readPropertiesForHist(CmsUser currentUser, CmsProject currentProject, String resource, String siteRoot, boolean search, int versionId) throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Looks up all properties for a resource.<p>
> *
> * @param resource the resource to look up the property for
> * @param versionId the requeste version of the resource
> * @return Map of Strings representing all properties of the resource
> * @throws CmsException in case there where problems reading the properties
> */
> public Map readProperties(String resource,int versionId) throws CmsException {
> return m_rb.readPropertiesForHist(m_context.currentUser(), m_context.currentProject(), m_context.getSiteRoot(resource), m_context.getSiteRoot(), false,versionId);
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Log channels in property file have wrong names and so they are never used.
>
> opencms.properties:
> old version:
> log.channel.module_debug=false
> log.channel.module_info=true
> log.channel.module_critical=true
>
> new version:
> log.channel.modules_debug=false
> log.channel.modules_info=true
> log.channel.modules_critical=true
>
> ---------------------------------------------------------------------------------------------------
>
> Bug 362
> When a folder is copied and the destination folder already exists, the copying fails.
> We added a check before creating the destination.
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - change method copyFile:
> old version:
> m_dbAccess.createFolder(currentUser,currentProject, onlineProject(currentUser, currentProject), folder,cmsFolder.getResourceId(),destination);
> new version:
> // Check if folder already exists before trying to create it
> CmsFolder oldFolder=null;
> try {
> oldFolder = readFolder(currentUser,currentProject,destination);
> } catch (CmsException e) {
> }
> if (oldFolder==null) m_dbAccess.createFolder(currentUser,currentProject, onlineProject(currentUser, currentProject), folder,cmsFolder.getResourceId(),destination);
>
> ---------------------------------------------------------------------------------------------------
>
> You cannot add new resource types if their classes are in a module.
> If you add resource types to registry.xml and the module is not installed yet,
> OpenCms stops with a ClassNotFoundException
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - change method getAllResourceTypes
> old version:
> }catch(Exception e){
> e.printStackTrace();
> throw new CmsException("[" + this.getClass().getName() + "] Error while getting ResourceType: "
> + (String)resTypeNames.elementAt(i) + " from registry ", CmsException.C_UNKNOWN_EXCEPTION );
> }
>
> new version:
> }catch(Exception e){
> e.printStackTrace();
> if (e instanceof ClassNotFoundException) {
> // ignore this exception.
> // maybe a module has added a new resource type to registry.xml
> // but the classes are not yet installed
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] Error while getting ResourceType: "
> + (String)resTypeNames.elementAt(i) + " from registry ", CmsException.C_UNKNOWN_EXCEPTION );
> }
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Bug 363:
> Moving or renaming a folder resource does not move the /system/bodies folder so bodies are lost for ever if you rename or move a folder.
> We fixed the bug by removing redundant code.
>
> com.opencms.file.CmsResourceTypeFolder.java:
> - change Method moveResource:
> old Version:
> public void moveResource(CmsObject cms, String source, String destination) throws CmsException{
> // it is a folder so we need the end /
> destination = destination +"/";
> // we have to copy the folder and all resources in the folder
> Vector allSubFolders = new Vector();
> Vector allSubFiles = new Vector();
> getAllResources(cms, source, allSubFiles, allSubFolders);
> if(!cms.accessWrite(source)){
> throw new CmsException(source, CmsException.C_NO_ACCESS);
> }
> // first copy the folder
> cms.doCopyFolder(source, destination);
> // now copy the subfolders
> for (int i=0; i<allSubFolders.size(); i++){
> CmsFolder curFolder = (CmsFolder) allSubFolders.elementAt(i);
> if(curFolder.getState() != C_STATE_DELETED){
> String curDestination = destination + curFolder.getAbsolutePath().substring(source.length());
> cms.doCopyFolder(curFolder.getAbsolutePath(), curDestination );
> }
> }
> // now move the files
> for (int i=0; i<allSubFiles.size(); i++){
> CmsFile curFile = (CmsFile)allSubFiles.elementAt(i);
> if(curFile.getState() != C_STATE_DELETED){
> String curDest = destination + curFile.getAbsolutePath().substring(source.length());
> cms.moveResource(curFile.getAbsolutePath(), curDest);
> }
> }
> // finaly remove the original folders
> deleteResource(cms, source);
> }
>
> new version:
> public void moveResource(CmsObject cms, String source, String destination) throws CmsException{
>
> copyResource(cms, source, destination, true);
> // finally remove the original folders
> deleteResource(cms, source);
> }
>
> - change Method renameResource:
> old version:
> public void renameResource(CmsObject cms, String oldname, String newname) throws CmsException{
> // first of all check the new name
> validResourcename(newname.replace('/','\n'));
> // we have to copy the folder and all resources in the folder
> Vector allSubFolders = new Vector();
> Vector allSubFiles = new Vector();
> getAllResources(cms, oldname, allSubFiles, allSubFolders);
> String parent = ((CmsResource)cms.readFileHeader(oldname)).getParent();
> if(!cms.accessWrite(oldname)){
> throw new CmsException(oldname, CmsException.C_NO_ACCESS);
> }
> if(!newname.endsWith("/")){
> newname = newname+"/";
> }
> // first copy the folder
> cms.doCopyFolder(oldname, parent + newname);
> // now copy the subfolders
> for (int i=0; i<allSubFolders.size(); i++){
> CmsFolder curFolder = (CmsFolder) allSubFolders.elementAt(i);
> if(curFolder.getState() != C_STATE_DELETED){
> String curDestination = parent + newname
> + curFolder.getAbsolutePath().substring(oldname.length());
> cms.doCopyFolder(curFolder.getAbsolutePath(), curDestination );
> }
> }
> // now move the files
> for (int i=0; i<allSubFiles.size(); i++){
> CmsFile curFile = (CmsFile)allSubFiles.elementAt(i);
> if(curFile.getState() != C_STATE_DELETED){
> String curDest = parent + newname
> + curFile.getAbsolutePath().substring(oldname.length());
> cms.moveResource(curFile.getAbsolutePath(), curDest);
> }
> }
> // finaly remove the original folders
> deleteResource(cms, oldname);
>
> }
>
> new version:
> public void renameResource(CmsObject cms, String oldname, String newname) throws CmsException{
> // first of all check the new name
> validResourcename(newname.replace('/','\n'));
>
> String parent = ((CmsResource)cms.readFileHeader(oldname)).getParent();
> if(!cms.accessWrite(oldname)){
> throw new CmsException(oldname, CmsException.C_NO_ACCESS);
> }
>
> moveResource(cms, oldname, parent + newname);
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Cms always sents Mails in charset ISO8859-1 so special chars not contained in this charset will get messed up.
> We changed the class to work with UTF-8 which is our default charset - would be better to choose charset dynamically
> from setup...
> See also Bug #83. We did not check the solution suggested there.
>
> com.opencms.defaults.CmsMail
> - change method buildMessage
> old version:
> // Default encoding for new mail message
> String mail_encoding = "ISO-8859-1";
>
> ...
>
> msg.setSentDate(new Date());
> return msg;
>
> version for UTF-8:
> // Default encoding for new mail message
> String mail_encoding = "UTF-8";
>
> ...
>
> msg.setSentDate(new Date());
> // following statement added because otherwise mail is always sent
> // with Content-Type "text/plain" in the header
> // and charset defaults to ISO-8859-1
> msg.setHeader("Content-Type", c_TYPE + "; charset=UTF-8");
>
> return msg;
>
> ---------------------------------------------------------------------------------------------------
>
> Link substitution ignores urls in <input src="..."> and <form action="...">
>
> com.opencms.util.LinkSubstitution.java:
> - change static String m_converterConfiguration
> old version:
> " <replacetags usedefaults=\"true\">"+
> " <tag name=\"img\" attrib=\"src\" replacestarttag=\"]]><LINK><![CDATA[$parameter$]]></LINK><![CDATA[\" parameter=\"src\" replaceparamattr=\"true\"/>"+
> " <tag name=\"a\" attrib=\"href\" replacestarttag=\"]]><LINK><![CDATA[$parameter$]]></LINK><![CDATA[\" replaceendtag=\"</a>\" parameter=\"href\" replaceparamattr=\"true\"/>"+
> " </replacetags>"+
>
> new version:
> " <replacetags usedefaults=\"true\">"+
> " <tag name=\"img\" attrib=\"src\" replacestarttag=\"]]><LINK><![CDATA[$parameter$]]></LINK><![CDATA[\" parameter=\"src\" replaceparamattr=\"true\"/>"+
> " <tag name=\"input\" attrib=\"src\" replacestarttag=\"]]><LINK><![CDATA[$parameter$]]></LINK><![CDATA[\" parameter=\"src\" replaceparamattr=\"true\"/>"+
> " <tag name=\"form\" attrib=\"action\" replacestarttag=\"]]><LINK><![CDATA[$parameter$]]></LINK><![CDATA[\" parameter=\"action\" replaceparamattr=\"true\"/>"+
> " <tag name=\"a\" attrib=\"href\" replacestarttag=\"]]><LINK><![CDATA[$parameter$]]></LINK><![CDATA[\" replaceendtag=\"</a>\" parameter=\"href\" replaceparamattr=\"true\"/>"+
> " </replacetags>"+
>
> ---------------------------------------------------------------------------------------------------
>
> The source editor cannot display special characters from Eastern Europe. We changed the default charset from FixedSys to Courier New
> which contains many more characters.
>
> /etc/ocsetup/vfs/system/workplace/templates/edit_text_main:
> old version:
> <!-- write the text area -->
> <script language="JavaScript">
> <!--
> str = '<textarea wrap="off" name="edit1" onfocus="setTextDelayed();" style="width:100%; height:100%; font-family:Fixedsys, monospace"></textarea>';
> document.write(str);
> //-->
> </script>
>
> new version:
> <!-- write the text area -->
> <script language="JavaScript">
> <!--
> str = '<textarea wrap="off" name="edit1" onfocus="setTextDelayed();" style="width:100%; height:100%; font-family:Courier New, monospace"></textarea>';
> document.write(str);
> //-->
>
> ---------------------------------------------------------------------------------------------------
>
> Some German spelling errors, mainly to fix different spellings of "Ressource".
>
> com.opencms.workplace.workplace_de.properties:
> old version:
> report.publish_resource_begin=Gebe Resource(n) frei ...
> report.publish_resource_end=... die Resource(n) wurde(n) freigegeben
> error.message.accessdenied=Leider konnte auf die Resource nicht zugegriffen werden.
> module.context.admin=Administieren
> flexcache.admin.label3=Zeige gecachte Resources mit Schlüsseln an
> flexcache.admin.label4=Zeige gecachte Resources mit Schlüsseln und Variationen an
> flexcache.admin.cached_resources=Momentan gecachte Resourcen
> flexcache.admin.cached_keys_variants=Gecachte Resourcen mit Schlüsseln und Variationen:
> flexcache.admin.cached_keys=Gecachte Resourcen mit Schlüsseln:
> flexcache.admin.online=Online Resourcen:
> flexcache.admin.offline=Offline Resourcen:
> flexcache.admin.err_online=Keine gecachten Online Resourcen!
> flexcache.admin.err_offline=Keine gecachten Offline Resourcen!
> flexcache.admin.resource=Resource
>
> new version:
> report.publish_resource_begin=Gebe Ressource(n) frei ...
> report.publish_resource_end=... die Ressource(n) wurde(n) freigegeben
> error.message.accessdenied=Leider konnte auf die Ressource nicht zugegriffen werden.
> module.context.admin=Administrieren
> flexcache.admin.label3=Zeige gecachte Ressourcen mit Schlüsseln an
> flexcache.admin.label4=Zeige gecachte Ressourcen mit Schlüsseln und Variationen an
> flexcache.admin.cached_resources=Momentan gecachte Ressourcen
> flexcache.admin.cached_keys_variants=Gecachte Ressourcen mit Schlüsseln und Variationen:
> flexcache.admin.cached_keys=Gecachte Ressourcen mit Schlüsseln:
> flexcache.admin.online=Online Ressourcen:
> flexcache.admin.offline=Offline Ressourcen:
> flexcache.admin.err_online=Keine gecachten Online Ressourcen!
> flexcache.admin.err_offline=Keine gecachten Offline Ressourcen!
> flexcache.admin.resource=Ressource
>
> ---------------------------------------------------------------------------------------------------
>
> CmsRequestContext.getSession fails with NullPointerException if no request is available
> which is possible if called in scheduled jobs.
>
> com.opencms.file.CmsRequestContext:
> - change method getSession
> old version:
> public I_CmsSession getSession(boolean value) {
> HttpSession session =
> ((HttpServletRequest) m_req.getOriginalRequest()).getSession(value);
> if (session != null) {
> return (I_CmsSession) new CmsSession(session);
> } else {
> return null;
> }
> }
>
> new version:
> public I_CmsSession getSession(boolean value) {
> // added checks for null.
> if (m_req == null || m_req.getOriginalRequest() == null) {
> return null;
> }
>
> HttpSession session =
> ((HttpServletRequest) m_req.getOriginalRequest()).getSession(value);
> if (session != null) {
> return (I_CmsSession) new CmsSession(session);
> } else {
> return null;
> }
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Fix for Bugzilla #74: Scheduler does not start jobs if the minute is 0.
>
> com.opencms.core.CmsCronEntry.java:
> - change Method check:
> old version:
> if(m_minute != C_ASTERIX) // check the minute
> if(!isBetween(lastTime.get(Calendar.MINUTE), m_minute, now.get(Calendar.MINUTE)))
> return false;
>
> new version:
> if(m_minute != C_ASTERIX) { // check the minute
> // changed to correct condition if lastTime was in last hour
> // (minute 59 < minute 0)
> int lastTimeMinute = lastTime.get(Calendar.MINUTE);
> int nowMinute = now.get(Calendar.MINUTE);
> while (lastTimeMinute > nowMinute) {
> lastTimeMinute -= 60;
> }
> if(!isBetween(lastTimeMinute, m_minute, nowMinute))
> return false;
> }
>
> ---------------------------------------------------------------------------------------------------
>
> On some systems, when creating a resource, the entered strings for property values (i.e. title) are not
> encoded correctly. German umlauts are replaced by question marks.
> We had this problem on a SUSE Linux using an IBM JDK and Java system property file.encoding=UTF-8.
> This could be solved by always explicitly specifying an encoding when converting Strings to bytes and back.
>
> com.opencms.utils.Encoder:
> - change method redecodeUriComponent:
> old version:
> public static String redecodeUriComponent(String input) {
> if (input == null) return input;
> return new String(changeEncoding(input.getBytes(), C_URI_ENCODING, A_OpenCms.getDefaultEncoding()));
> }
>
> new version:
> public static String redecodeUriComponent(String input) {
> if (input == null) return input;
> // added encoding for getBytes and new String because otherwise
> // platform default encoding is used which may destroy some characters
> try {
> return new String(changeEncoding(input.getBytes(C_URI_ENCODING), C_URI_ENCODING, A_OpenCms.getDefaultEncoding()),
> A_OpenCms.getDefaultEncoding());
> } catch (UnsupportedEncodingException e) {
> return new String(changeEncoding(input.getBytes(), C_URI_ENCODING, A_OpenCms.getDefaultEncoding()));
> }
> }
>
> ---------------------------------------------------------------------------------------------------
>
> It is impossible to disable the scheduler when creating a new CmsObject because this property is always read from
> system properties, ignoring the specified properties (this behaviour is different from all other properties)
>
> com.opencms.core.OpenCms:
> - change constructor OpenCms
> old version:
> // if the System property opencms.disableScheduler is set to true, don't start scheduling
> if(!new Boolean(System.getProperty("opencms.disableScheduler")).booleanValue()) {
> // now initialise the OpenCms scheduler to launch cronjobs
> m_table = new CmsCronTable(m_resourceBroker.readCronTable(null, null));
> m_scheduler = new CmsCronScheduler(this, m_table);
> if(C_LOGGING && isLogging(C_OPENCMS_INIT)) log(C_OPENCMS_INIT, ". OpenCms scheduler : enabled");
> } else {
> if(C_LOGGING && isLogging(C_OPENCMS_INIT)) log(C_OPENCMS_INIT, ". OpenCms scheduler : disabled");
> }
> new version:
> // if the property opencms.disableScheduler is set to true, don't start scheduling
> if(!conf.getBoolean("opencms.disableScheduler", false)) {
> // now initialise the OpenCms scheduler to launch cronjobs
> m_table = new CmsCronTable(m_resourceBroker.readCronTable(null, null));
> m_scheduler = new CmsCronScheduler(this, m_table);
> if(C_LOGGING && isLogging(C_OPENCMS_INIT)) log(C_OPENCMS_INIT, ". OpenCms scheduler : enabled");
> } else {
> if(C_LOGGING && isLogging(C_OPENCMS_INIT)) log(C_OPENCMS_INIT, ". OpenCms scheduler : disabled");
> }
>
> ---------------------------------------------------------------------------------------------------
>
> In CmsResourceBroker some methods change the file-state after saving the file. That does not make sense.
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - change method writeProperty:
> old version:
> if(res.isFile()){
> m_dbAccess.writeFileHeader(currentProject, (CmsFile) res, true, currentUser.getId());
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> } else {
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> m_dbAccess.writeFolder(currentProject, readFolder(currentUser,currentProject, resource), true, currentUser.getId());
> }
> new version:
> if(res.isFile()){
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> m_dbAccess.writeFileHeader(currentProject, (CmsFile) res, true, currentUser.getId());
> } else {
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> m_dbAccess.writeFolder(currentProject, readFolder(currentUser,currentProject, resource), true, currentUser.getId());
> }
>
>
> The same holds for methods chgrp, chmod, chown, chtype, deleteProperty, writeFile, writeFileHeader.
>
>
>
> ---------------------------------------------------------------------------------------------------
>
> If copying a resource, the owner and group are also copied from the source. So if you copy a resource not owned by yourself,
> you may not be allowed to change it afterwards. As you are not the owner, you cannot change the owner to yourself after copying.
> When copying files in a real file system, the owner is changed so we implemented the same behaviour for VFS.
> As moving and renaming is implemented by copy & delete, the same holds for move and rename.
>
> This change could only be realized at a level below the access checks, because otherwise we would not have the privilege to change the owner.
> Therefore, we had to change some signatures.
>
> com.opencms.file.genericSql.CmsDbAccess
> - add return value to method copyFile
> old version:
> /**
> * Copies the file.
> *
> * @param project The project in which the resource will be used.
> * @param onlineProject The online project of the OpenCms.
> * @param userId The id of the user who wants to copy the file.
> * @param source The complete path of the sourcefile.
> * @param parentId The parentId of the resource.
> * @param destination The complete path of the destinationfile.
> *
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public void copyFile(CmsProject project,
> CmsProject onlineProject,
> int userId,
> String source,
> int parentId,
> String destination)
> throws CmsException {
> CmsFile file;
>
> // read sourcefile
> file=readFile(project.getId(),onlineProject.getId(),source);
> // create destination file
> createFile(project,onlineProject,file,userId,parentId,destination);
> }
>
> new version:
> /**
> * Copies the file.
> *
> * @param project The project in which the resource will be used.
> * @param onlineProject The online project of the OpenCms.
> * @param userId The id of the user who wants to copy the file.
> * @param source The complete path of the sourcefile.
> * @param parentId The parentId of the resource.
> * @param destination The complete path of the destinationfile.
> *
> * @return the created destination file
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public CmsFile copyFile(CmsProject project,
> CmsProject onlineProject,
> int userId,
> String source,
> int parentId,
> String destination)
> throws CmsException {
> CmsFile file;
>
> // read sourcefile
> file=readFile(project.getId(),onlineProject.getId(),source);
> // create destination file
> return createFile(project,onlineProject,file,userId,parentId,destination);
> }
>
>
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - change method copyFile:
> old version:
> /**
> * Copies a file in the Cms. <br>
> *
> * <B>Security:</B>
> * Access is granted, if:
> * <ul>
> * <li>the user has access to the project</li>
> * <li>the user can read the sourceresource</li>
> * <li>the user can create the destinationresource</li>
> * <li>the destinationresource doesn't exist</li>
> * </ul>
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param source The complete path of the sourcefile.
> * @param destination The complete path to the destination.
> *
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public void copyFile(CmsUser currentUser, CmsProject currentProject,
> String source, String destination)
> throws CmsException {
>
> // the name of the new file.
> String filename;
> // the name of the folder.
> String foldername;
>
> // checks, if the destinateion is valid, if not it throws a exception
> validFilename(destination.replace('/', 'a'));
>
> // read the source-file, to check readaccess
> CmsResource file = readFileHeader(currentUser, currentProject, source);
>
> // split the destination into file and foldername
> if (destination.endsWith("/")) {
> filename = file.getName();
> foldername = destination;
> }else{
> foldername = destination.substring(0, destination.lastIndexOf("/")+1);
> filename = destination.substring(destination.lastIndexOf("/")+1,
> destination.length());
> }
>
> CmsFolder cmsFolder = readFolder(currentUser,currentProject, foldername);
> if( accessCreate(currentUser, currentProject, (CmsResource)cmsFolder) ) {
> if(( accessOther(file, C_ACCESS_PUBLIC_WRITE) ||
> accessOwner(currentUser, currentProject, file, C_ACCESS_OWNER_WRITE) ||
> accessGroup(currentUser, currentProject, file, C_ACCESS_GROUP_WRITE) )){
> // write-acces was granted - copy the file and the metainfos
> m_dbAccess.copyFile(currentProject, onlineProject(currentUser, currentProject),
> currentUser.getId(),source,cmsFolder.getResourceId(), foldername + filename);
>
> this.clearResourceCache(foldername + filename, currentProject, currentUser);
> // copy the metainfos
> lockResource(currentUser, currentProject, destination, true);
> writeProperties(currentUser,currentProject, destination,
> readProperties(currentUser, currentProject, file.getResourceName(), null, false));
> m_accessCache.clear();
> // inform about the file-system-change
> fileSystemChanged(file.isFolder());
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + source,
> CmsException.C_NO_ACCESS);
> }
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + destination,
> CmsException.C_NO_ACCESS);
> }
> }
>
> new version:
> /**
> * Copies a file in the Cms. <br>
> * The owner and the group of the copied file are set to current user and group. <br>
> *
> * <B>Security:</B>
> * Access is granted, if:
> * <ul>
> * <li>the user has access to the project</li>
> * <li>the user can read the sourceresource</li>
> * <li>the user can create the destinationresource</li>
> * <li>the destinationresource doesn't exist</li>
> * </ul>
> *
> * @param currentUser The user who requested this method.
> * @param currentGroup The current group of the user.
> * @param currentProject The current project of the user.
> * @param source The complete path of the sourcefile.
> * @param destination The complete path to the destination.
> *
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public void copyFile(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject,
> String source, String destination)
> throws CmsException {
>
> // the name of the new file.
> String filename;
> // the name of the folder.
> String foldername;
>
> // checks, if the destinateion is valid, if not it throws a exception
> validFilename(destination.replace('/', 'a'));
>
> // read the source-file, to check readaccess
> CmsResource file = readFileHeader(currentUser, currentProject, source);
>
> // split the destination into file and foldername
> if (destination.endsWith("/")) {
> filename = file.getName();
> foldername = destination;
> }else{
> foldername = destination.substring(0, destination.lastIndexOf("/")+1);
> filename = destination.substring(destination.lastIndexOf("/")+1,
> destination.length());
> }
>
> CmsFolder cmsFolder = readFolder(currentUser,currentProject, foldername);
> if( accessCreate(currentUser, currentProject, (CmsResource)cmsFolder) ) {
> if(( accessOther(file, C_ACCESS_PUBLIC_WRITE) ||
> accessOwner(currentUser, currentProject, file, C_ACCESS_OWNER_WRITE) ||
> accessGroup(currentUser, currentProject, file, C_ACCESS_GROUP_WRITE) )){
> // write-acces was granted - copy the file and the metainfos
> CmsFile destinationFile = m_dbAccess.copyFile(currentProject, onlineProject(currentUser, currentProject),
> currentUser.getId(),source,cmsFolder.getResourceId(), foldername + filename);
>
> this.clearResourceCache(foldername + filename, currentProject, currentUser);
> // copy the metainfos
> lockResource(currentUser, currentProject, destination, true);
> destinationFile.setLocked(currentUser.getId());
> destinationFile.setLockedInProject(currentProject.getId());
> writeProperties(currentUser,currentProject, destination,
> readProperties(currentUser, currentProject, file.getResourceName(), null, false));
> // set user and group to currentUser (otherwise the currentUser could not change it
> // because the copy is also owned by source owner).
> // we cannot use chown/chgrp here because of access checks!
> destinationFile.setUserId(currentUser.getId());
> destinationFile.setGroupId(currentGroup.getId());
> m_dbAccess.writeFileHeader(currentProject, destinationFile, true, currentUser.getId());
> this.clearResourceCache(filename, currentProject, currentUser);
> m_accessCache.clear();
> // inform about the file-system-change
> fileSystemChanged(file.isFolder());
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + source,
> CmsException.C_NO_ACCESS);
> }
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + destination,
> CmsException.C_NO_ACCESS);
> }
> }
>
> - change method copyFolder
> old version:
> /**
> * Copies a folder in the Cms. <br>
> *
> * <B>Security:</B>
> * Access is granted, if:
> * <ul>
> * <li>the user has access to the project</li>
> * <li>the user can read the sourceresource</li>
> * <li>the user can create the destinationresource</li>
> * <li>the destinationresource doesn't exist</li>
> * </ul>
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param source The complete path of the sourcefolder.
> * @param destination The complete path to the destination.
> *
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public void copyFolder(CmsUser currentUser, CmsProject currentProject,
> String source, String destination)
> throws CmsException {
>
> // the name of the folder.
> String foldername;
>
> // checks, if the destinateion is valid, if not it throws a exception
> validFilename(destination.replace('/', 'a'));
> foldername = destination.substring(0, destination.substring(0,destination.length()-1).lastIndexOf("/")+1);
> CmsFolder cmsFolder = readFolder(currentUser,currentProject, foldername);
> if( accessCreate(currentUser, currentProject, (CmsResource)cmsFolder) ) {
> // write-acces was granted - copy the folder and the properties
> CmsFolder folder=readFolder(currentUser,currentProject,source);
> // check write access to the folder that has to be copied
> if(( accessOther((CmsResource)folder, C_ACCESS_PUBLIC_WRITE) ||
> accessOwner(currentUser, currentProject, (CmsResource)folder, C_ACCESS_OWNER_WRITE) ||
> accessGroup(currentUser, currentProject, (CmsResource)folder, C_ACCESS_GROUP_WRITE) )){
> m_dbAccess.createFolder(currentUser,currentProject, onlineProject(currentUser, currentProject), folder,cmsFolder.getResourceId(),destination);
> this.clearResourceCache(destination, currentProject, currentUser);
> // copy the properties
> lockResource(currentUser, currentProject, destination, true);
> writeProperties(currentUser,currentProject, destination,
> readProperties(currentUser, currentProject, folder.getResourceName(), null, false));
> m_resourceListCache.clear();
> m_accessCache.clear();
> // inform about the file-system-change
> fileSystemChanged(true);
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + source,
> CmsException.C_ACCESS_DENIED);
> }
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + destination,
> CmsException.C_ACCESS_DENIED);
> }
>
> }
>
> new version:
> /**
> * Copies a folder in the Cms. <br>
> * The owner and the group of the copied folder are set to current user and group. <br>
> *
> * <B>Security:</B>
> * Access is granted, if:
> * <ul>
> * <li>the user has access to the project</li>
> * <li>the user can read the sourceresource</li>
> * <li>the user can create the destinationresource</li>
> * <li>the destinationresource doesn't exist</li>
> * </ul>
> *
> * @param currentUser The user who requested this method.
> * @param currentGroup The current group of the user.
> * @param currentProject The current project of the user.
> * @param source The complete path of the sourcefolder.
> * @param destination The complete path to the destination.
> *
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public void copyFolder(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject,
> String source, String destination)
> throws CmsException {
>
> // the name of the folder.
> String foldername;
>
> // checks, if the destinateion is valid, if not it throws a exception
> validFilename(destination.replace('/', 'a'));
> foldername = destination.substring(0, destination.substring(0,destination.length()-1).lastIndexOf("/")+1);
> CmsFolder cmsFolder = readFolder(currentUser,currentProject, foldername);
> if( accessCreate(currentUser, currentProject, (CmsResource)cmsFolder) ) {
> // write-acces was granted - copy the folder and the properties
> CmsFolder folder=readFolder(currentUser,currentProject,source);
> // check write access to the folder that has to be copied
> if(( accessOther((CmsResource)folder, C_ACCESS_PUBLIC_WRITE) ||
> accessOwner(currentUser, currentProject, (CmsResource)folder, C_ACCESS_OWNER_WRITE) ||
> accessGroup(currentUser, currentProject, (CmsResource)folder, C_ACCESS_GROUP_WRITE) )){
> // Check if folder already exists before trying to create it
> CmsFolder destinationFolder=null;
> try {
> destinationFolder = readFolder(currentUser,currentProject,destination);
> } catch (CmsException e) {
> }
> if (destinationFolder==null) {
> destinationFolder = m_dbAccess.createFolder(currentUser,currentProject, onlineProject(currentUser, currentProject), folder,cmsFolder.getResourceId(),destination);}
> this.clearResourceCache(destination, currentProject, currentUser);
> // copy the properties
> lockResource(currentUser, currentProject, destination, true);
> destinationFolder.setLocked(currentUser.getId());
> destinationFolder.setLockedInProject(currentProject.getId());
> writeProperties(currentUser,currentProject, destination,
> readProperties(currentUser, currentProject, folder.getResourceName(), null, false));
> // set user and group to currentUser (otherwise the currentUser could not change it
> // because the copy is also owned by source owner).
> // we cannot use chown/chgrp here because of access checks!
> destinationFolder.setUserId(currentUser.getId());
> destinationFolder.setGroupId(currentGroup.getId());
> m_dbAccess.writeFolder(currentProject, destinationFolder, true, currentUser.getId());
> this.clearResourceCache(destination, currentProject, currentUser);
>
> m_resourceListCache.clear();
> m_accessCache.clear();
> // inform about the file-system-change
> fileSystemChanged(true);
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + source,
> CmsException.C_ACCESS_DENIED);
> }
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + destination,
> CmsException.C_ACCESS_DENIED);
> }
>
> }
>
> - change method moveFile:
> old version:
> /**
> * Moves the file.
> *
> * This operation includes a copy and a delete operation. These operations
> * are done with their security-checks.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param source The complete path of the sourcefile.
> * @param destination The complete path of the destinationfile.
> *
> * @throws CmsException will be thrown, if the file couldn't be moved.
> * The CmsException will also be thrown, if the user has not the rights
> * for this resource.
> */
> public void moveFile(CmsUser currentUser, CmsProject currentProject, String source, String destination) throws CmsException {
>
> // read the file to check access
> CmsResource file = readFileHeader(currentUser,currentProject, source);
>
> // has the user write-access?
> if (accessWrite(currentUser, currentProject, file)) {
>
> // first copy the file, this may ends with an exception
> copyFile(currentUser, currentProject, source, destination);
>
> // then delete the source-file, this may end with an exception
> // => the file was only copied, not moved!
> deleteFile(currentUser, currentProject, source);
> // inform about the file-system-change
> fileSystemChanged(file.isFolder());
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + source, CmsException.C_NO_ACCESS);
> }
> }
>
> new version:
> /**
> * Moves the file.
> *
> * This operation includes a copy and a delete operation. These operations
> * are done with their security-checks.
> *
> * @param currentUser The user who requested this method.
> * @param currentGroup The current group of the user.
> * @param currentProject The current project of the user.
> * @param source The complete path of the sourcefile.
> * @param destination The complete path of the destinationfile.
> *
> * @throws CmsException will be thrown, if the file couldn't be moved.
> * The CmsException will also be thrown, if the user has not the rights
> * for this resource.
> */
> public void moveFile(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject, String source, String destination) throws CmsException {
>
> // read the file to check access
> CmsResource file = readFileHeader(currentUser,currentProject, source);
>
> // has the user write-access?
> if (accessWrite(currentUser, currentProject, file)) {
>
> // first copy the file, this may ends with an exception
> copyFile(currentUser, currentGroup, currentProject, source, destination);
>
> // then delete the source-file, this may end with an exception
> // => the file was only copied, not moved!
> deleteFile(currentUser, currentProject, source);
> // inform about the file-system-change
> fileSystemChanged(file.isFolder());
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + source, CmsException.C_NO_ACCESS);
> }
> }
>
> - change method renameFile
> old version:
> /**
> * Renames the file to a new name. <br>
> *
> * Rename can only be done in an offline project. To rename a file, the following
> * steps have to be done:
> * <ul>
> * <li> Copy the file with the oldname to a file with the new name, the state
> * of the new file is set to NEW (2).
> * <ul>
> * <li> If the state of the original file is UNCHANGED (0), the file content of the
> * file is read from the online project. </li>
> * <li> If the state of the original file is CHANGED (1) or NEW (2) the file content
> * of the file is read from the offline project. </li>
> * </ul>
> * </li>
> * <li> Set the state of the old file to DELETED (3). </li>
> * </ul>
> *
> * <B>Security:</B>
> * Access is granted, if:
> * <ul>
> * <li>the user has access to the project</li>
> * <li>the user can write the resource</li>
> * <li>the resource is locked by the callingUser</li>
> * </ul>
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param oldname The complete path to the resource which will be renamed.
> * @param newname The new name of the resource (CmsUser callingUser, No path information allowed).
> *
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public void renameFile(CmsUser currentUser, CmsProject currentProject, String oldname, String newname) throws CmsException {
>
> // read the old file
> CmsResource file = readFileHeader(currentUser, currentProject, oldname);
>
> // checks, if the newname is valid, if not it throws a exception
> validFilename(newname);
>
> // has the user write-access?
> if (accessWrite(currentUser, currentProject, file)) {
> String path = oldname.substring(0, oldname.lastIndexOf("/") + 1);
> copyFile(currentUser, currentProject, oldname, path + newname);
> deleteFile(currentUser, currentProject, oldname);
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + oldname, CmsException.C_NO_ACCESS);
> }
> }
>
> new version:
> /**
> * Renames the file to a new name. <br>
> *
> * Rename can only be done in an offline project. To rename a file, the following
> * steps have to be done:
> * <ul>
> * <li> Copy the file with the oldname to a file with the new name, the state
> * of the new file is set to NEW (2).
> * <ul>
> * <li> If the state of the original file is UNCHANGED (0), the file content of the
> * file is read from the online project. </li>
> * <li> If the state of the original file is CHANGED (1) or NEW (2) the file content
> * of the file is read from the offline project. </li>
> * </ul>
> * </li>
> * <li> Set the state of the old file to DELETED (3). </li>
> * </ul>
> *
> * <B>Security:</B>
> * Access is granted, if:
> * <ul>
> * <li>the user has access to the project</li>
> * <li>the user can write the resource</li>
> * <li>the resource is locked by the callingUser</li>
> * </ul>
> *
> * @param currentUser The user who requested this method.
> * @param currentGroup The current group of the user.
> * @param currentProject The current project of the user.
> * @param oldname The complete path to the resource which will be renamed.
> * @param newname The new name of the resource (CmsUser callingUser, No path information allowed).
> *
> * @throws CmsException Throws CmsException if operation was not succesful.
> */
> public void renameFile(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject, String oldname, String newname) throws CmsException {
>
> // read the old file
> CmsResource file = readFileHeader(currentUser, currentProject, oldname);
>
> // checks, if the newname is valid, if not it throws a exception
> validFilename(newname);
>
> // has the user write-access?
> if (accessWrite(currentUser, currentProject, file)) {
> String path = oldname.substring(0, oldname.lastIndexOf("/") + 1);
> copyFile(currentUser, currentGroup, currentProject, oldname, path + newname);
> deleteFile(currentUser, currentProject, oldname);
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + oldname, CmsException.C_NO_ACCESS);
> }
> }
>
> com.opencms.file.I_CmsResourceBroker
> - add parameter currentGroup to the following methods
> new version:
> public void copyFile(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject,
> String source, String destination)
> throws CmsException;
> public void copyFolder(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject,
> String source, String destination)
> throws CmsException;
> public void moveFile(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject,
> String source, String destination)
> throws CmsException;
> public void renameFile(CmsUser currentUser, CmsGroup currentGroup, CmsProject currentProject,
> String oldname, String newname)
> throws CmsException;
>
> com.opencms.file.CmsObject
> - add parameter currentGroup to broker call in the following methods (signature of CmsObject methods remains unchanged)
> new version:
> protected void doCopyFile(String source, String destination) throws CmsException {
> m_rb.copyFile(m_context.currentUser(), m_context.currentGroup(), m_context.currentProject(), getSiteRoot(source), getSiteRoot(destination));
> }
> protected void doCopyFolder(String source, String destination) throws CmsException {
> m_rb.copyFolder(m_context.currentUser(), m_context.currentGroup(), m_context.currentProject(), getSiteRoot(source), getSiteRoot(destination));
> }
> protected void doMoveFile(String source, String destination) throws CmsException {
> m_rb.moveFile(m_context.currentUser(), m_context.currentGroup(), m_context.currentProject(), getSiteRoot(source), getSiteRoot(destination));
> }
> protected void doRenameFile(String oldname, String newname) throws CmsException {
> m_rb.renameFile(m_context.currentUser(), m_context.currentGroup(), m_context.currentProject(), getSiteRoot(oldname), newname);
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Fix for Bug 348: CmsResourceBroker.readAllFileHeadersForHist throws a CmsException if the
> resource has been deleted. The method calls readFileHeader to check read access
> to the resource. This fails if the resource has already been deleted. A method
> called "forHist" should only access backup resources as they still exists even
> for deleted files.
>
> As other forHist methods also do not have an access check, we removed the check here.
>
> com.opencms.file.genericSql.CmsResourceBroker
> - change method readAllFileHeadersForHist
> old version:
> public Vector readAllFileHeadersForHist(CmsUser currentUser, CmsProject currentProject,
> String filename)
> throws CmsException {
> CmsResource cmsFile = readFileHeader(currentUser,currentProject, filename);
> if( accessRead(currentUser, currentProject, cmsFile) ) {
>
> // access to all subfolders was granted - return the file-history.
> return(m_dbAccess.readAllFileHeadersForHist(filename));
> } else {
> throw new CmsException("[" + this.getClass().getName() + "] " + filename,
> CmsException.C_ACCESS_DENIED);
> }
> }
>
> new version:
> public Vector readAllFileHeadersForHist(CmsUser currentUser, CmsProject currentProject,
> String filename)
> throws CmsException {
>
> return(m_dbAccess.readAllFileHeadersForHist(filename));
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Two different backup versions of a resource are considered equal. CmsBackupResource.equals() should
> not only check the file name but also the version id.
>
> com.opencms.file.CmsBackupResource:
> - add method equals
> /**
> * Compares the overgiven object with this object.
> * Two CmsBackupResources are considered equal if they have the same absolute resource name
> * and the same version id.
> * @return true, if the object is identically else it returns false.
> */
> public boolean equals(Object obj) {
> boolean equal;
> if (obj instanceof CmsBackupResource) {
> // parent class checks only resource name, not enough for backups
> equal=super.equals(obj);
> if (equal) {
> // same version ID than the current resource?
> if (((CmsBackupResource)obj).getVersionId() != m_versionId){
> equal = false;
> }
> }
> } else {
> equal = false;
> }
>
> return equal;
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Bug 364:
> Trying to send a mail from a scheduled job fails with NullPointerException.
> Reason: CmsMail always tries to get additional attachments from request, that is not available in a scheduled job.
>
> com.opencms.defaults.CmsMail
> - change method buildMessage
> old version:
> // Set content and attachments
> Vector v = new Vector();
> if (c_CMS != null){
> Enumeration enum = c_CMS.getRequestContext().getRequest().getFileNames();
> while(enum.hasMoreElements()) {
> v.addElement(enum.nextElement());
> }
> }
>
> new version:
> // Set content and attachments
> Vector v = new Vector();
> if (c_CMS != null && c_CMS.getRequestContext() != null && c_CMS.getRequestContext().getRequest() != null){
> Enumeration enum = c_CMS.getRequestContext().getRequest().getFileNames();
> while(enum.hasMoreElements()) {
> v.addElement(enum.nextElement());
> }
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Bug 365
> Access checks for read and visible return a wrong result if the user has these privileges via his group.
>
> com.opencms.file.genericSql.CmsResourceBroker
> - change method accessReadVisible
> 1st change, old version:
> if ((resource == null) || !accessProject(currentUser, currentProject, resource.getProjectId()) ||
> (!accessOther(resource, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE) &&
> !accessOwner(currentUser, currentProject, resource, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE) &&
> !accessGroup(currentUser, currentProject, resource, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE))) {
> return false;
> }
> 1st change, new version:
> if ((resource == null) || !accessProject(currentUser, currentProject, resource.getProjectId()) ||
> (!accessOther(resource, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE) &&
> !accessOwner(currentUser, currentProject, resource, C_ACCESS_OWNER_READ + C_ACCESS_OWNER_VISIBLE) &&
> !accessGroup(currentUser, currentProject, resource, C_ACCESS_GROUP_READ + C_ACCESS_GROUP_VISIBLE))) {
> return false;
> }
>
> 2nd change, old version:
> if (!accessOther(res, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE) &&
> !accessOwner(currentUser, currentProject, res, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE) &&
> !accessGroup(currentUser, currentProject, res, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE)) {
> return false;
> }
> 2nd change, new version:
> if (!accessOther(res, C_ACCESS_PUBLIC_READ + C_ACCESS_PUBLIC_VISIBLE) &&
> !accessOwner(currentUser, currentProject, res, C_ACCESS_OWNER_READ + C_ACCESS_OWNER_VISIBLE) &&
> !accessGroup(currentUser, currentProject, res, C_ACCESS_GROUP_READ + C_ACCESS_GROUP_VISIBLE)) {
> return false;
> }
>
> ---------------------------------------------------------------------------------------------------
>
>
>
> ------------------------------------------------------------------------
>
> Enhancements for OpenCms 5.0.1:
> -------------------------------
>
> This file lists the enhancements made by GETIT GmbH for productional use of OpenCms 5.0.1.
>
> ---------------------------------------------------------------------------------------------------
>
> Change the group for a resource recursively from CmsShell:
>
> com.opencms.coreCmsShellCommands.java, new method:
> /**
> * Changes the group for this resource recursively<BR/>
> *
> * The user may change this, if he is admin of the resource.
> *
> * @param filename The complete path to the resource.
> * @param newGroup The new of the new group for this resource.
> * @param recursively shows if the subResources (of a folder) should be changed too.
> */
> public void chgrp(String filename, String newGroup, String recursively) {
> try {
> m_cms.chgrp(filename, newGroup,
> recursively.toLowerCase().equals("true"));
> }
> catch(Exception exc) {
> CmsShell.printException(exc);
> }
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Methods to access a project with a specific name from CmsShell
> In 5.0.1, you can also change to a project if you have its project id. If you create a project
> using CmsShell, you specify its name but you do not know its id. So you cannot do anything with this
> project later. We added some methods using the name as parameter.
>
> com.opencms.coreCmsShellCommands.java, new methods:
> /**
> * Sets the current project for the user.
> *
> * @param name The name of the project to be set as current.
> * There should be only one project with this name,
> * otherwise this call sets the first project found.
> */
> public void setCurrentProjectWithName(String name) {
> try {
>
> Vector projects = m_cms.getAllAccessibleProjects();
> for(int i = 0;i < projects.size();i++) {
> CmsProject project = (CmsProject)projects.elementAt(i);
> if (project.getName().equals(name)) {
> System.out.println(m_cms.getRequestContext()
> .setCurrentProject(project.getId()));
> break;
> }
> }
> }
> catch(Exception exc) {
> CmsShell.printException(exc);
> }
> }
>
> /**
> * Deletes all projects with a specified name.
> *
> * @param name The name of the project to be deleted.
> * There should be only one project with this name,
> * otherwise this call deletes all projects found!
> */
> public void deleteProjectWithName(String name) {
> try {
> Vector projects = m_cms.getAllAccessibleProjects();
> for(int i = 0;i < projects.size();i++) {
> CmsProject project = (CmsProject)projects.elementAt(i);
> if (project.getName().equals(name)) {
> m_cms.deleteProject(project.getId());
> }
> }
> }
> catch(Exception exc) {
> CmsShell.printException(exc);
> }
> }
>
>
> ---------------------------------------------------------------------------------------------------
>
> Methods to read properties from a backup version for a resource:
>
> com.opencms.file.genericSql.CmsDbAccess:
> - new method:
> /**
> * Returns a list of all history properties of a file or folder.<p>
> *
> * @param resourceId the id of the resource
> * @param resource the resource to read the properties from
> * @param resourceType the type of the resource
> *
> * @return a Map of Strings representing the properties of the resource
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public HashMap readPropertiesForHist(CmsResource resource, int resourceType)
> throws CmsException {
>
> HashMap returnValue = new HashMap();
> ResultSet result = null;
> PreparedStatement statement = null;
> Connection con = null;
> String usedPool;
> int resourceId = resource.getResourceId();
> //int onlineProject = getOnlineProject(projectId).getId();
> usedPool = m_poolNameBackup;
> try {
> con = DriverManager.getConnection(usedPool);
> // create project
> statement = con.prepareStatement(m_cq.get("C_PROPERTIES_READALL_BACKUP"));
> statement.setInt(1, resourceId);
> statement.setInt(2, resourceType);
> result = statement.executeQuery();
> while(result.next()) {
> returnValue.put(result.getString(m_cq.get("C_PROPERTYDEF_NAME")),
> result.getString(m_cq.get("C_PROPERTY_VALUE")));
> }
> } catch( SQLException exc ) {
> throw new CmsException("[" + this.getClass().getName() + "] " + exc.getMessage(),
> CmsException.C_SQL_ERROR, exc);
> } finally {
> // close all db-resources
> if(result != null) {
> try {
> result.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(statement != null) {
> try {
> statement.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(con != null) {
> try {
> con.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> }
> return(returnValue);
> }
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - new constant:
> protected static final String C_CACHE_ALL_BACKUP_PROPERTIES = "__CACHE_ALL_BACKUP_PROPERTIES__";
>
> - new method:
> /**
> * Looks up all properties for a resource with optional direcory upward cascading.<p>
> *
> *
> * @param currentUser the current user
> * @param currentProject the current project of the user
> * @param resource the resource to look up the property for
> * @param siteRoot the current site root
> * @param search if <code>true</code>, the properties will also be looked up on all parent folders
> * and the results will be merged, if <code>false</code> not (ie. normal property lookup)
> * @return Map of Strings representing all properties of the resource
> * @throws CmsException in case there where problems reading the properties
> */
> public Map readPropertiesForHist(CmsUser currentUser, CmsProject currentProject, String resource, String siteRoot, boolean search, int version_id)
> throws CmsException {
> // read the resource from history
> CmsResource res = readFileForHist (currentUser, currentProject, version_id,resource);
>
> search = search && (siteRoot != null);
> // check if we have the result already cached
> HashMap value = null;
>
> String cacheKey = getCacheKey(C_CACHE_ALL_BACKUP_PROPERTIES + search+version_id, null, new CmsProject(currentProject.getId(), -1), res.getResourceName());
> value = (HashMap)m_propertyCache.get(cacheKey);
>
> if (value == null) {
> // result not cached, let's look it up in the DB
> if (search) {
> boolean cont;
> siteRoot += "/";
> value = new HashMap();
> HashMap parentValue;
> do {
> parentValue = (HashMap)readProperties(currentUser, currentProject, resource, siteRoot, false);
> parentValue.putAll(value);
> value.clear();
> value.putAll(parentValue);
> resource = CmsResource.getParent(resource);
> cont = (! siteRoot.equals(resource));
> } while (cont);
> } else {
> value = m_dbAccess.readPropertiesForHist(res, res.getType());
> }
> // store the result in the cache
> m_propertyCache.put(cacheKey, value);
> }
> return (Map)value.clone();
> }
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * Looks up all properties from ab backup resource with optional direcory upward cascading.<p>
> *
> * <b>Security:</b>
> * Only a user is granted who has the right to read the resource.
> *
> * @param currentUser the current user
> * @param currentProject the current project of the user
> * @param resource the resource to look up the property for
> * @param siteroot the site root where to stop the cascading
> * @param search if <code>true</code>, the properties will also be looked up on all parent folders
> * and the results will be merged, if <code>false</code> not (ie. normal property lookup)
> * @param versionId the version id containing the defined properties
> * @return Map of Strings representing all properties of the resource
> * @throws CmsException in case there where problems reading the properties
> */
> public Map readPropertiesForHist(CmsUser currentUser, CmsProject currentProject, String resource, String siteRoot, boolean search, int versionId) throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Looks up all properties for a resource.<p>
> *
> * @param resource the resource to look up the property for
> * @param versionId the requeste version of the resource
> * @return Map of Strings representing all properties of the resource
> * @throws CmsException in case there where problems reading the properties
> */
> public Map readProperties(String resource,int versionId) throws CmsException {
> return m_rb.readPropertiesForHist(m_context.currentUser(), m_context.currentProject(), m_context.getSiteRoot(resource), m_context.getSiteRoot(), false,versionId);
> }
>
> ---------------------------------------------------------------------------------------------------
>
> CmsSetupUtils cannot read Property values containing a comma. We enhanced the class to read commas when escaped as \,
>
> com.opencms.boot.CmsSetupUtils:
> - change method splitMultipleValues:
> old version:
> private String splitMultipleValues(String value) {
> String tempValue = "";
> StringTokenizer st = new StringTokenizer(value,",");
> int counter = 1;
> int max = st.countTokens();
> while(st.hasMoreTokens()) {
> tempValue += st.nextToken().trim();
> if(counter < max) {
> tempValue += ", \\ \n";
> }
> counter++;
> }
> return tempValue;
> }
> new version:
> private String splitMultipleValues(String value) {
> StringBuffer tmp = new StringBuffer();
> int start = 0;
> int stop = -1;
> while (stop<value.length()) {
> stop = value.indexOf(',',stop+1);
> while (stop>=1 && value.charAt(stop-1)=='\\') {
> stop = value.indexOf(',',stop+1);
> }
> if (stop==-1) stop=value.length();
> tmp.append(value.substring(start,stop).trim());
> if (stop<value.length()) tmp.append(", \\ \n");
> start=stop+1;
> }
> return tmp.toString();
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Functionality for users to be logged in without a password. Can be used in scheduled jobs.
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - new method:
>
> /**
> * Logs a user into the Cms, if the password is correct.
> *
> * <B>Security</B>
> * All users are granted.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param username The name of the user to be returned.
> * @param password The password of the user to be returned.
> * @return the logged in user.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public CmsUser loginUser(CmsUser currentUser, CmsProject currentProject,
> String username)
> throws CmsException {
>
> // we must read the user from the dbAccess to avoid the cache
> CmsUser newUser = m_dbAccess.readUser(username , C_USER_TYPE_SYSTEMUSER);
>
> // is the user enabled?
> if( newUser.getFlags() == C_FLAG_ENABLED ) {
> // Yes - log him in!
> // first write the lastlogin-time.
> newUser.setLastlogin(new Date().getTime());
> // write the user back to the cms.
> m_dbAccess.writeUser(newUser);
> // update cache
> m_userCache.put(new CacheId(newUser), newUser);
> return(newUser);
> } else {
> // No Access!
> throw new CmsException("[" + this.getClass().getName() + "] " + username,
> CmsException.C_NO_ACCESS );
> }
> }
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * Logs a user into the Cms, no password is needed.
> *
> * <B>Security</B>
> * All users are granted.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param username The name of the user to be returned.
> * @return the logged in user.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public CmsUser loginUser(CmsUser currentUser, CmsProject currentProject,
> String username)
> throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Logs a user into the Cms withou providing a password
> *
> * @param username the name of the user.
> * @return the name of the logged in user.
> *
> * @throws CmsException if operation was not successful
> */
> public String loginUser(String username) throws CmsException {
> // login the user
> CmsUser newUser = m_rb.loginUser(m_context.currentUser(), m_context.currentProject(), username);
> // init the new user
> init(m_rb, m_context.getRequest(), m_context.getResponse(), newUser.getName(), newUser.getDefaultGroup().getName(), C_PROJECT_ONLINE_ID, m_context.isStreaming(), m_context.getElementCache(), m_sessionStorage, m_context.getDirectoryTranslator(), m_context.getFileTranslator());
>
> this.fireEvent(com.opencms.flex.I_CmsEventListener.EVENT_LOGIN_USER, newUser);
>
> // return the user-name
> this.fireEvent(com.opencms.flex.I_CmsEventListener.EVENT_LOGIN_USER, newUser);
> return (newUser.getName());
> }
>
> ---------------------------------------------------------------------------------------------------
>
> Workplace Popup for folder tree always starts with root folder. We added a parameter to specify another root folder.
>
> com.opencms.workplace.I_CmsWpConstants:
> - new constant:
> /** Parameter for rootfolder */
> public static final String C_PARA_ROOTFOLDER = "rootfolder";
>
> com.opencms.workplace.CmsFolderTree:
> - change method getTree:
> old version:
> // get current and root folder
> rootFolder = cms.rootFolder().getAbsolutePath();
>
> new version:
> // get current and root folder
> rootFolder = cms.getRequestContext().getRequest().getParameter(C_PARA_ROOTFOLDER);
> if ((rootFolder == null) || (rootFolder.equals("")))
> rootFolder = cms.rootFolder().getAbsolutePath();
>
>
> ---------------------------------------------------------------------------------------------------
>
> You cannot get a specific project by its name.
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Get project id of the project with the given name
> *
> * @param name The name of the project to be set as current. There should be
> * only one project with this name, otherwise this call sets the
> * first project found.
> * @return The ID of the project if found, -1 if not
> */
> public int getProjectWithName(String name) throws CmsException {
> Vector projects = getAllAccessibleProjects();
> for (int i = 0; i < projects.size(); i++) {
> CmsProject project = (CmsProject) projects.elementAt(i);
> if (project.getName().equals(name)) {
> return project.getId();
> }
> }
> return -1;
> }
>
> ---------------------------------------------------------------------------------------------------
>
> If you write a property and the property definition does not exist, you should be able to automatically
> create the definition. Methods for this only exist in DbAccess unreachable for modules.
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - change method writeProperty and add new method with different signature
> old version:
> /**
> * Writes a propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation has
> * to be read.
> * @param property The propertydefinition-name of which the propertyinformation has to be set.
> * @param value The value for the propertyinfo to be set.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperty(CmsUser currentUser, CmsProject currentProject,
> String resource, String property, String value)
> throws CmsException {
>
> // read the resource
> CmsResource res = readFileHeader(currentUser,currentProject, resource);
>
> // check the security
> if( ! accessWrite(currentUser, currentProject, res) ) {
> throw new CmsException("[" + this.getClass().getName() + "] " + resource,
> CmsException.C_NO_ACCESS);
> }
>
> m_dbAccess.writeProperty(property, currentProject.getId(),value, res,res.getType(), false);
> m_propertyCache.clear();
> // set the file-state to changed
> if(res.isFile()){
> m_dbAccess.writeFileHeader(currentProject, (CmsFile) res, true, currentUser.getId());
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> } else {
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> m_dbAccess.writeFolder(currentProject, readFolder(currentUser,currentProject, resource), true, currentUser.getId());
> }
> // update the cache
> this.clearResourceCache(resource, currentProject, currentUser);
> }
>
> new version:
> /**
> * Writes a propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation has
> * to be read.
> * @param property The propertydefinition-name of which the propertyinformation has to be set.
> * @param value The value for the propertyinfo to be set.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperty(CmsUser currentUser, CmsProject currentProject,
> String resource, String property, String value)
> throws CmsException {
> writeProperty(currentUser, currentProject, resource, property, value, false);
> }
>
> /**
> * Writes a propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation has
> * to be read.
> * @param property The propertydefinition-name of which the propertyinformation has to be set.
> * @param value The value for the propertyinfo to be set.
> * @param addDefinition If <code>true</code> then the propertydefinition is added if it not exists
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperty(CmsUser currentUser, CmsProject currentProject,
> String resource, String property, String value, boolean addDefinition)
> throws CmsException {
>
> // read the resource
> CmsResource res = readFileHeader(currentUser,currentProject, resource);
>
> // check the security
> if( ! accessWrite(currentUser, currentProject, res) ) {
> throw new CmsException("[" + this.getClass().getName() + "] " + resource,
> CmsException.C_NO_ACCESS);
> }
>
> m_dbAccess.writeProperty(property, currentProject.getId(),value, res,res.getType(), addDefinition);
> m_propertyCache.clear();
> // set the file-state to changed
> if(res.isFile()){
> m_dbAccess.writeFileHeader(currentProject, (CmsFile) res, true, currentUser.getId());
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> } else {
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> m_dbAccess.writeFolder(currentProject, readFolder(currentUser,currentProject, resource), true, currentUser.getId());
> }
> // update the cache
> this.clearResourceCache(resource, currentProject, currentUser);
> }
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * Writes a propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation has
> * to be read.
> * @param property The propertydefinition-name of which the propertyinformation has to be set.
> * @param value The value for the propertyinfo to be set.
> * @param addDefinition If <code>true</code> then the propertydefinition is added if it not exists
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperty(CmsUser currentUser, CmsProject currentProject,
> String resource, String property, String value, boolean addDefinition)
> throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Writes a property for a file or folder.
> *
> * @param name the resource-name for which the property will be set.
> * @param property the property-definition name.
> * @param value the value for the property to be set.
> * @param addDefinition If <code>true</code> then the propertydefinition is added if it not exists
> *
> * @throws CmsException if operation was not successful.
> */
> public void writeProperty(String name, String property, String value, boolean addDefinition) throws CmsException {
> m_rb.writeProperty(m_context.currentUser(), m_context.currentProject(), getSiteRoot(name), property, value, addDefinition);
> }
>
> ---------------------------------------------------------------------------------------------------
>
> If you write some properties and any of the property definitions does not exist, you should be able to automatically
> create the definition. Methods for this only exist in DbAccess unreachable for modules.
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - change method writeProperties and add new method with different signature
> old version:
> /**
> * Writes a couple of propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation
> * has to be read.
> * @param propertyinfos A Hashtable with propertydefinition- propertyinfo-pairs as strings.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperties(CmsUser currentUser, CmsProject currentProject,
> String resource, Map propertyinfos)
> throws CmsException {
> // read the resource
>
>
> CmsResource res = readFileHeader(currentUser,currentProject, resource);
>
> // check the security
> if( ! accessWrite(currentUser, currentProject, res) ) {
> throw new CmsException("[" + this.getClass().getName() + "] " + resource,
> CmsException.C_NO_ACCESS);
> }
>
> m_dbAccess.writeProperties(propertyinfos, currentProject.getId(), res, res.getType());
> m_propertyCache.clear();
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> if(res.isFile()){
> m_dbAccess.writeFileHeader(currentProject, (CmsFile) res, false, currentUser.getId());
> } else {
> m_dbAccess.writeFolder(currentProject, readFolder(currentUser,currentProject, resource), false, currentUser.getId());
> }
> // update the cache
> this.clearResourceCache(resource, currentProject, currentUser);
> }
>
> new version:
> /**
> * Writes a couple of propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation
> * has to be read.
> * @param propertyinfos A Hashtable with propertydefinition- propertyinfo-pairs as strings.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperties(CmsUser currentUser, CmsProject currentProject,
> String resource, Map propertyinfos)
> throws CmsException {
> writeProperties(currentUser, currentProject, resource, propertyinfos, false);
> }
>
> /**
> * Writes a couple of propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation
> * has to be read.
> * @param propertyinfos A Hashtable with propertydefinition- propertyinfo-pairs as strings.
> * @param addDefinition If <code>true</code> then the propertydefinition is added if it not exists
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperties(CmsUser currentUser, CmsProject currentProject,
> String resource, Map propertyinfos, boolean addDefinition)
> throws CmsException {
> // read the resource
>
>
> CmsResource res = readFileHeader(currentUser,currentProject, resource);
>
> // check the security
> if( ! accessWrite(currentUser, currentProject, res) ) {
> throw new CmsException("[" + this.getClass().getName() + "] " + resource,
> CmsException.C_NO_ACCESS);
> }
>
> m_dbAccess.writeProperties(propertyinfos, currentProject.getId(), res, res.getType(), addDefinition);
> m_propertyCache.clear();
> if (res.getState()==C_STATE_UNCHANGED) {
> res.setState(C_STATE_CHANGED);
> }
> if(res.isFile()){
> m_dbAccess.writeFileHeader(currentProject, (CmsFile) res, false, currentUser.getId());
> } else {
> m_dbAccess.writeFolder(currentProject, readFolder(currentUser,currentProject, resource), false, currentUser.getId());
> }
> // update the cache
> this.clearResourceCache(resource, currentProject, currentUser);
> }
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * Writes a couple of propertyinformation for a file or folder.
> *
> * <B>Security</B>
> * Only the user is granted, who has the right to write the resource.
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resource The name of the resource of which the propertyinformation
> * has to be read.
> * @param propertyinfos A Hashtable with propertydefinition- propertyinfo-pairs as strings.
> * @param addDefinition If <code>true</code> then the propertydefinition is added if it not exists
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public void writeProperties(CmsUser currentUser, CmsProject currentProject,
> String resource, Map propertyinfos, boolean addDefinition)
> throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Writes a couple of Properties for a file or folder.
> *
> * @param name the resource-name of which the Property has to be set.
> * @param properties a Hashtable with property-definitions and property values as Strings.
> * @param addDefinition If <code>true</code> then the propertydefinition is added if it not exists
> *
> * @throws CmsException if operation was not successful.
> */
> public void writeProperties(String name, Map properties, boolean addDefinition) throws CmsException {
> m_rb.writeProperties(m_context.currentUser(), m_context.currentProject(), getSiteRoot(name), properties, addDefinition);
> }
>
>
> ---------------------------------------------------------------------------------------------------
>
> We missed a method to find a folder with a specific name searching only through a part of VFS. As relative folder names are not unique,
> the following method returns only the first folder found.
>
> com.opencms.file.genericSql.query.properties:
> - add properties:
> C_RESOURCES_FIND_FIRST_FOLDER_1=SELECT CMS_RESOURCES.RESOURCE_NAME \
> FROM CMS_RESOURCES, CMS_PROJECTRESOURCES \
> WHERE CMS_RESOURCES.RESOURCE_NAME LIKE '
> C_RESOURCES_FIND_FIRST_FOLDER_2=' AND CMS_RESOURCES.RESOURCE_TYPE = 0 \
> AND CMS_RESOURCES.RESOURCE_NAME LIKE CONCAT(CMS_PROJECTRESOURCES.RESOURCE_NAME,'%') \
> AND CMS_PROJECTRESOURCES.PROJECT_ID IN (?, 1) \
> ORDER BY CMS_RESOURCES.RESOURCE_NAME, CMS_PROJECTRESOURCES.PROJECT_ID DESC
> C_RESOURCES_FIND_FIRST_FOLDER_1_ONLINE=SELECT CMS_ONLINE_RESOURCES.RESOURCE_NAME \
> FROM CMS_ONLINE_RESOURCES \
> WHERE RESOURCE_NAME LIKE '
> C_RESOURCES_FIND_FIRST_FOLDER_2_ONLINE=' AND PROJECT_ID = ?
>
>
> com.opencms.file.genericSql.CmsDbAccess:
> - new method:
> /**
> * Searches for a vfs folder with a specific relative name.
> * @param project The project in which the resource will be used.
> * @param folderName relative name of a vfs folder
> * @param rootFolderName absolute vfs name of the folder to search in
> * @return absolute name of the first folder found recursively under rootFolderName which name is folderName
> * null if no folder found
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public String getFirstFolderWithName(CmsProject project, String folderName, String rootFolderName)
> throws CmsException {
>
> ResultSet res = null;
> PreparedStatement statement = null;
> Connection con = null;
> String usedPool;
> String usedStatement;
> String resourcename = rootFolderName + "%" + folderName;
> String absolutename = null;
> int onlineProject = I_CmsConstants.C_PROJECT_ONLINE_ID;
> if (project.getId() == onlineProject){
> usedPool = m_poolNameOnline;
> usedStatement = "_ONLINE";
> } else {
> usedPool = m_poolName;
> usedStatement = "";
> }
> try {
> con = DriverManager.getConnection(usedPool);
> // read resource data from database
> statement = con.prepareStatement(m_cq.get("C_RESOURCES_FIND_FIRST_FOLDER_1"+usedStatement)+"/default/vfs"+resourcename+m_cq.get("C_RESOURCES_FIND_FIRST_FOLDER_2"+usedStatement));
> statement.setInt(1,project.getId());
> res = statement.executeQuery();
> // get resource name from first resource in the result
> if(res.next()) {
> absolutename=res.getString(m_cq.get("C_RESOURCES_RESOURCE_NAME"));
> if (absolutename.startsWith("/default/vfs")) {
> absolutename = absolutename.substring("/default/vfs".length());
> }
> }
> } catch (SQLException e){
> throw new CmsException("["+this.getClass().getName()+"]"+e.getMessage(),CmsException.C_SQL_ERROR, e);
> } catch (Exception ex) {
> throw new CmsException("["+this.getClass().getName()+"]", ex);
> } finally {
> // close all db-resources
> if(res != null) {
> try {
> res.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(statement != null) {
> try {
> statement.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(con != null) {
> try {
> con.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> }
> return absolutename;
> }
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - new method:
> /**
> * Searches for a vfs folder with a specific relative name.
> * @param currentUser ignored in this method
> * @param currentProject The project in which the resource will be used.
> * @param folderName relative name of a vfs folder
> * @param rootFolderName absolute vfs name of the folder to search in
> * @return absolute name of the first folder found recursively under rootFolderName which name is folderName
> * null if no folder found
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public String getFirstFolderWithName(CmsUser currentUser, CmsProject currentProject, String folderName, String rootFolderName) throws CmsException {
> return m_dbAccess.getFirstFolderWithName(currentProject, folderName, rootFolderName);
> }
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * Searches for a vfs folder with a specific relative name.
> * @param currentUser ignored in this method
> * @param currentProject The project in which the resource will be used.
> * @param folderName relative name of a vfs folder
> * @param rootFolderName absolute vfs name of the folder to search in
> * @return absolute name of the first folder found recursively under rootFolderName which name is folderName
> * null if no folder found
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public String getFirstFolderWithName(CmsUser currentUser, CmsProject currentProject, String folderName, String rootFolderName) throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Searches for a vfs folder with a specific relative name.
> * @param folderName relative name of a vfs folder
> * @param rootFolderName absolute vfs name of the folder to search in
> * @return absolute name of the first folder found recursively under rootFolderName which name is folderName
> * null if no folder found
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public String getFirstFolderWithName(String folderName, String rootFolderName) throws CmsException {
> return m_rb.getFirstFolderWithName(m_context.currentUser(), m_context.currentProject(), folderName, rootFolderName);
> }
>
> ---------------------------------------------------------------------------------------------------
>
> We added a method to find all resources in a folder that have been published after a specific date.
> This only works if backup is enabled cause a resource's publish date is only stored in the backup resource.
>
> com.opencms.file.genericSql.query.properties:
> - add properties:
> # all resources that match a filter and have been published afer a specified date
> # only works correct if backup is enabled cause otherwise no publish date is saved
> C_SELECT_LAST_PUBLISHED_RESOURCES=SELECT DISTINCT RESOURCE_NAME \
> FROM CMS_BACKUP_RESOURCES \
> WHERE TO_CHAR(DATE_CREATED, 'YYYY-MM-DD HH24:MI:SS') > ? \
> AND RESOURCE_NAME LIKE ?
> ORDER BY RESOURCE_NAME
>
> com.opencms.file.mySql.query.properties:
> C_SELECT_LAST_PUBLISHED_RESOURCES=SELECT DISTINCT RESOURCE_NAME \
> FROM CMS_BACKUP_RESOURCES \
> WHERE DATE_CREATED > ? \
> AND RESOURCE_NAME LIKE ?
> ORDER BY RESOURCE_NAME
>
> com.opencms.file.genericSql.CmsDbAccess:
> - new imports:
> import java.text.SimpleDateFormat;
> import java.util.Date;
> import java.util.GregorianCalendar;
>
> - new method:
> /**
> * select the names of all resources that have been published after a specific time
> * and belong to a specific root folder
> *
> * @param startDate a date
> * @param folderName absolute name of a VFS folder
> * @return a collection of all resource names from resources
> * @author Sven Bonorden, GETIT GmbH
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public Vector getLastPublishedResources(Date startDate, String folderName) throws CmsException {
> if (startDate == null) {
> GregorianCalendar cal = new GregorianCalendar(1970,1,1);
> startDate = new Date(cal.getTimeInMillis());
> }
> String startDateString = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(startDate);
>
> if (folderName == null || folderName.length()==0) {
> folderName = "";
> }
> if (!folderName.startsWith("/default/vfs")) {
> folderName = "/default/vfs" + folderName;
> }
>
> Connection con = null;
> PreparedStatement statement = null;
> ResultSet res = null;
> Vector publishedResources = new Vector();
> try {
> con = DriverManager.getConnection(m_poolNameBackup);
> statement = con.prepareStatement(m_cq.get("C_SELECT_LAST_PUBLISHED_RESOURCES"));
>
> statement.setString(1, startDateString);
> statement.setString(2, folderName + "%");
>
> res = statement.executeQuery();
> while (res.next()) {
> publishedResources.addElement(res.getString("RESOURCE_NAME"));
> }
> res.close();
> } catch (SQLException e) {
> throw new CmsException("[" + this.getClass().getName() + "] " + e.getMessage(), CmsException.C_SQL_ERROR, e);
> } finally {
> if (statement != null) {
> try{
> statement.close();
> } catch (SQLException e){
> }
> }
> if (con != null) {
> try{
> con.close();
> } catch (SQLException e){
> }
> }
> }
> return publishedResources;
> }
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - new method:
> /**
> * select the names of all resources that have been published after a specific time
> * and belong to a specific root folder
> *
> * @param startDate a date
> * @param folderName absolute name of a VFS folder
> * @return a collection of all resource names from resources
> * @author Sven Bonorden, GETIT GmbH
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public Vector getLastPublishedResources(Date startDate, String folderName) throws CmsException {
> return m_dbAccess.getLastPublishedResources(startDate, folderName);
> }
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * select the names of all resources that have been published after a specific time
> * and belong to a specific root folder
> *
> * @param startDate a date
> * @param folderName absolute name of a VFS folder
> * @return a collection of all resource names from resources
> * @author Sven Bonorden, GETIT GmbH
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public Vector getLastPublishedResources(Date startDate, String folderName)
> throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Select the names of all resources that have been published after a specific time
> * and belong to a specific root folder.
> * This method ignores access priviledges and projects, all published files are returned.
> *
> * @param startDate a date
> * @param folderName absolute name of a VFS folder
> * @return a collection of all resource names from resources
> * @author Sven Bonorden, GETIT GmbH
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public Vector getLastPublishedResources(Date startDate, String folderName) throws CmsException {
> return m_rb.getLastPublishedResources(startDate, folderName);
> }
>
> ---------------------------------------------------------------------------------------------------
>
> It was impossible to get the resource type of a deleted resource (that is still available in the backup).
>
> com.opencms.file.genericSql.query.properties:
> - add properties:
> C_RESOURCES_READ_ALL_BACKUP_ORDER_DESC=SELECT CMS_BACKUP_RESOURCES.*, CMS_BACKUP_RESOURCES.PROJECT_ID LOCKED_IN_PROJECT \
> FROM CMS_BACKUP_RESOURCES WHERE RESOURCE_NAME=? \
> ORDER BY VERSION_ID DESC
>
> com.opencms.file.genericSql.CmsDbAccess:
> - new method:
> /**
> * Reads the resource type of a historic file in the OpenCms.<BR>
> *
> * @param resourceName The name of the file to be read.
> * @return resource type of the last backed-up version of this resource.
> * @throws CmsException Throws CmsException if operation was not succesful
> * @author Sven Bonorden, GETIT GmbH
> */
> public int getResourceTypeForHist(String resourceName)
> throws CmsException {
>
> int resourceType = -1;
> ResultSet res =null;
> PreparedStatement statement = null;
> Connection con = null;
>
> try {
> con = DriverManager.getConnection(m_poolNameBackup);
> statement = con.prepareStatement(m_cq.get("C_RESOURCES_READ_ALL_BACKUP_ORDER_DESC"));
> // read file header data from database
> statement.setString(1, resourceName);
> res = statement.executeQuery();
> // read only the first row because this is the last version of the resource
> if(res.next()) {
> resourceType= res.getInt(m_cq.get("C_RESOURCES_RESOURCE_TYPE"));
> }
> } catch (SQLException e){
> throw new CmsException("["+this.getClass().getName()+"] "+e.getMessage(),CmsException.C_SQL_ERROR, e);
> } catch( Exception exc ) {
> throw new CmsException("readResourceTypeForHist "+exc.getMessage(), CmsException.C_UNKNOWN_EXCEPTION, exc);
> } finally {
> // close all db-resources
> if(res != null) {
> try {
> res.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(statement != null) {
> try {
> statement.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> if(con != null) {
> try {
> con.close();
> } catch(SQLException exc) {
> // nothing to do here
> }
> }
> }
> return resourceType;
> }
>
> com.opencms.file.genericSql.CmsResourceBroker:
> - new method:
> /**
> * Reads the resource type of a historic file in the OpenCms.<BR>
> * No security checks.
> *
> * @author Sven Bonorden, GETIT GmbH
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resourceName The name of the file to be read.
> *
> * @return resource type of the last backed-up version of this resource.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public int getResourceTypeForHist(CmsUser currentUser, CmsProject currentProject, String resourceName)
> throws CmsException {
> // no security check, accessRead cannot be used if the file was deleted.
>
> return(m_dbAccess.getResourceTypeForHist(resourceName));
> }
>
> com.opencms.file.I_CmsResourceBroker:
> - new method:
> /**
> * Reads the resource type of a historic file in the OpenCms.<BR>
> * No security checks.
> *
> * @author Sven Bonorden, GETIT GmbH
> *
> * @param currentUser The user who requested this method.
> * @param currentProject The current project of the user.
> * @param resourceName The name of the file to be read.
> *
> * @return resource type of the last backed-up version of this resource.
> *
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public int getResourceTypeForHist(CmsUser currentUser, CmsProject currentProject, String resourceName)
> throws CmsException;
>
> com.opencms.file.CmsObject:
> - new method:
> /**
> * Reads the resource type of a historic file in the OpenCms.<BR>
> * No security checks as this method must also work if the file has been deleted.
> *
> * @author Sven Bonorden, GETIT GmbH
> *
> * @param resourceName The name of the file to be read.
> * @return resource type of the last backed-up version of this resource.
> * @throws CmsException Throws CmsException if operation was not succesful
> */
> public int getResourceTypeForHist(String resourceName) throws CmsException {
> return (m_rb.getResourceTypeForHist(m_context.currentUser(), m_context.currentProject(), getSiteRoot(resourceName)));
> }
>
> ---------------------------------------------------------------------------------------------------
>
> We enhanced the folder tree popup to show not only the name, but also the title of the resource (if it is different from the name).
> This was necessary because our customer needed many folders named by internal ids and only the title showed readable information.
> As this change leads to slower performance, it must be checked if useful for other projects.
>
> com.opencms.workplace.CmsFolderTree:
> - change method showTree:
> old version:
> template.setData(C_TREEENTRY, res.getName());
>
> new version:
> String name = res.getName();
> String title = cms.readProperty(res.getAbsolutePath(), C_PROPERTY_TITLE);
> if (title != null && title.trim().length() > 0 && !title.equalsIgnoreCase(name)) {
> name = name + " (" + title + ")";
> }
> template.setData(C_TREEENTRY, name);
>
>
> ---------------------------------------------------------------------------------------------------
>
More information about the opencms-dev
mailing list