001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.forms.data; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.sql.Connection; 021import java.sql.PreparedStatement; 022import java.sql.ResultSet; 023import java.sql.SQLException; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.cocoon.ProcessingException; 028import org.apache.cocoon.reading.ServiceableReader; 029import org.apache.commons.lang.StringUtils; 030import org.apache.excalibur.source.SourceUtil; 031import org.xml.sax.SAXException; 032 033import org.ametys.core.datasource.ConnectionHelper; 034import org.ametys.core.datasource.dbtype.SQLDatabaseTypeExtensionPoint; 035import org.ametys.core.user.CurrentUserProvider; 036import org.ametys.core.user.UserIdentity; 037import org.ametys.plugins.forms.table.FormTableManager; 038import org.ametys.runtime.authentication.AccessDeniedException; 039import org.ametys.runtime.config.Config; 040import org.ametys.web.renderingcontext.RenderingContext; 041import org.ametys.web.renderingcontext.RenderingContextHandler; 042 043/** 044 * Reads a BLOB value of a form entry. 045 */ 046public class FormEntryFileReader extends ServiceableReader 047{ 048 private CurrentUserProvider _currentUserProvider; 049 050 private SQLDatabaseTypeExtensionPoint _sqlDatabaseTypeExtensionPoint; 051 052 private RenderingContextHandler _renderingContextHandler; 053 054 private SQLDatabaseTypeExtensionPoint getSQLDatabaseTypeExtensionPoint() 055 { 056 if (_sqlDatabaseTypeExtensionPoint == null) 057 { 058 try 059 { 060 _sqlDatabaseTypeExtensionPoint = (SQLDatabaseTypeExtensionPoint) manager.lookup(SQLDatabaseTypeExtensionPoint.ROLE); 061 } 062 catch (ServiceException e) 063 { 064 throw new RuntimeException(e); 065 } 066 } 067 return _sqlDatabaseTypeExtensionPoint; 068 } 069 070 @Override 071 public void service(ServiceManager smanager) throws ServiceException 072 { 073 super.service(smanager); 074 _renderingContextHandler = (RenderingContextHandler) smanager.lookup(RenderingContextHandler.ROLE); 075 _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 076 } 077 078 @Override 079 public void generate() throws IOException, SAXException, ProcessingException 080 { 081 String siteName = parameters.getParameter("site", ""); 082 String formId = parameters.getParameter("form-id", ""); 083 int entryId = parameters.getParameterAsInteger("entry-id", Integer.MIN_VALUE); 084 String fieldId = parameters.getParameter("field-id", ""); 085 086 if (StringUtils.isEmpty(siteName) || StringUtils.isEmpty(formId) 087 || entryId == Integer.MIN_VALUE || StringUtils.isEmpty(fieldId)) 088 { 089 throw new IllegalArgumentException("Site name, form id, entry id and field id must be provided."); 090 } 091 092 String tableName = FormTableManager.TABLE_PREFIX + formId; 093 094 Connection connection = null; 095 PreparedStatement stmt = null; 096 ResultSet rs = null; 097 098 try 099 { 100 String dataSourceId = Config.getInstance().getValue(FormTableManager.FORMS_POOL_CONFIG_PARAM); 101 connection = ConnectionHelper.getConnection(dataSourceId); 102 103 String dbType = ConnectionHelper.getDatabaseType(connection); 104 String sql = "SELECT " + getSQLDatabaseTypeExtensionPoint().languageEscapeTableName(dbType, fieldId) 105 + "," + FormTableManager.LOGIN_FIELD 106 + "," + FormTableManager.POPULATION_ID_FIELD 107 + " FROM " + getSQLDatabaseTypeExtensionPoint().languageEscapeTableName(dbType, tableName) 108 + " WHERE id = ?"; 109 110 stmt = connection.prepareStatement(sql); 111 112 stmt.setInt(1, entryId); 113 114 // Execute the query. 115 rs = stmt.executeQuery(); 116 117 // Extract the result. 118 if (rs.next()) 119 { 120 String login = rs.getString(FormTableManager.LOGIN_FIELD); 121 String population = rs.getString(FormTableManager.POPULATION_ID_FIELD); 122 123 _checkAccess(login, population); 124 125 try (InputStream is = _sqlDatabaseTypeExtensionPoint.getBlob(dbType, rs, 1)) 126 { 127 if (is != null) 128 { 129 SourceUtil.copy(is, out); 130 } 131 } 132 } 133 } 134 catch (SQLException e) 135 { 136 getLogger().error("Error reading a form entry blob." + tableName, e); 137 throw new ProcessingException("Error reading a form entry blob.", e); 138 } 139 finally 140 { 141 ConnectionHelper.cleanup(rs); 142 ConnectionHelper.cleanup(stmt); 143 ConnectionHelper.cleanup(connection); 144 } 145 } 146 147 private void _checkAccess(String login, String population) 148 { 149 UserIdentity entryOwner = null; 150 if (StringUtils.isNotEmpty(login) && StringUtils.isNotEmpty(population)) 151 { 152 entryOwner = new UserIdentity(login, population); 153 } 154 155 RenderingContext context = _renderingContextHandler.getRenderingContext(); 156 if (context == RenderingContext.FRONT) 157 { 158 // If request come from front, check user is the file owner 159 UserIdentity currentUser = _currentUserProvider.getUser(); 160 if (entryOwner == null || !entryOwner.equals(currentUser)) 161 { 162 throw new AccessDeniedException("User '" + currentUser + "' is not allowed to access to user entry data."); 163 } 164 } 165 } 166}