001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.webdav;
016    
017    import com.liferay.portal.kernel.dao.orm.QueryUtil;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.FileUtil;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.HttpUtil;
025    import com.liferay.portal.kernel.util.OrderByComparator;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.util.StringUtil;
028    import com.liferay.portal.kernel.util.Time;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.kernel.xml.Namespace;
031    import com.liferay.portal.kernel.xml.SAXReaderUtil;
032    import com.liferay.portal.model.Group;
033    import com.liferay.portal.model.GroupConstants;
034    import com.liferay.portal.model.User;
035    import com.liferay.portal.service.GroupLocalServiceUtil;
036    import com.liferay.portal.service.UserLocalServiceUtil;
037    import com.liferay.portal.util.comparator.GroupFriendlyURLComparator;
038    import com.liferay.portlet.documentlibrary.util.DL;
039    import com.liferay.registry.Registry;
040    import com.liferay.registry.RegistryUtil;
041    import com.liferay.registry.ServiceReference;
042    import com.liferay.registry.ServiceRegistration;
043    import com.liferay.registry.ServiceTracker;
044    import com.liferay.registry.ServiceTrackerCustomizer;
045    import com.liferay.registry.collections.ServiceRegistrationMap;
046    
047    import java.util.ArrayList;
048    import java.util.Collection;
049    import java.util.Collections;
050    import java.util.HashSet;
051    import java.util.LinkedHashMap;
052    import java.util.List;
053    import java.util.Map;
054    import java.util.Set;
055    import java.util.concurrent.ConcurrentSkipListMap;
056    
057    import javax.servlet.http.HttpServletRequest;
058    
059    /**
060     * @author Brian Wing Shun Chan
061     * @author Alexander Chow
062     * @author Raymond Aug??
063     */
064    public class WebDAVUtil {
065    
066            public static final Namespace DAV_URI = SAXReaderUtil.createNamespace(
067                    "D", "DAV:");
068    
069            public static final int SC_LOCKED = 423;
070    
071            public static final int SC_MULTI_STATUS = 207;
072    
073            public static final String TOKEN_PREFIX = "opaquelocktoken:";
074    
075            public static void addStorage(WebDAVStorage storage) {
076                    getInstance()._addStorage(storage);
077            }
078    
079            public static Namespace createNamespace(String prefix, String uri) {
080                    Namespace namespace = null;
081    
082                    if (uri.equals(WebDAVUtil.DAV_URI.getURI())) {
083                            namespace = WebDAVUtil.DAV_URI;
084                    }
085                    else if (Validator.isNull(prefix)) {
086                            namespace = SAXReaderUtil.createNamespace(uri);
087                    }
088                    else {
089                            namespace = SAXReaderUtil.createNamespace(prefix, uri);
090                    }
091    
092                    return namespace;
093            }
094    
095            public static void deleteStorage(WebDAVStorage storage) {
096                    getInstance()._deleteStorage(storage);
097            }
098    
099            public static long getDepth(HttpServletRequest request) {
100                    String value = GetterUtil.getString(request.getHeader("Depth"));
101    
102                    if (_log.isDebugEnabled()) {
103                            _log.debug("\"Depth\" header is " + value);
104                    }
105    
106                    if (value.equals("0")) {
107                            return 0;
108                    }
109                    else {
110                            return -1;
111                    }
112            }
113    
114            public static String getDestination(
115                    HttpServletRequest request, String rootPath) {
116    
117                    String headerDestination = request.getHeader("Destination");
118                    String[] pathSegments = StringUtil.split(headerDestination, rootPath);
119    
120                    String destination = pathSegments[pathSegments.length - 1];
121    
122                    destination = HttpUtil.decodePath(destination);
123    
124                    if (_log.isDebugEnabled()) {
125                            _log.debug("Destination " + destination);
126                    }
127    
128                    return destination;
129            }
130    
131            public static long getGroupId(long companyId, String path)
132                    throws WebDAVException {
133    
134                    String[] pathArray = getPathArray(path);
135    
136                    return getGroupId(companyId, pathArray);
137            }
138    
139            public static long getGroupId(long companyId, String[] pathArray)
140                    throws WebDAVException {
141    
142                    try {
143                            if (pathArray.length == 0) {
144                                    return 0;
145                            }
146    
147                            String name = pathArray[0];
148    
149                            Group group = GroupLocalServiceUtil.fetchFriendlyURLGroup(
150                                    companyId, StringPool.SLASH + name);
151    
152                            if (group != null) {
153                                    return group.getGroupId();
154                            }
155    
156                            User user = UserLocalServiceUtil.fetchUserByScreenName(
157                                    companyId, name);
158    
159                            if (user != null) {
160                                    group = user.getGroup();
161    
162                                    return group.getGroupId();
163                            }
164                    }
165                    catch (Exception e) {
166                            throw new WebDAVException(e);
167                    }
168    
169                    return 0;
170            }
171    
172            public static List<Group> getGroups(long userId) throws Exception {
173                    User user = UserLocalServiceUtil.getUser(userId);
174    
175                    return getGroups(user);
176            }
177    
178            public static List<Group> getGroups(User user) throws Exception {
179    
180                    // Guest
181    
182                    if (user.isDefaultUser()) {
183                            List<Group> groups = new ArrayList<Group>();
184    
185                            Group group = GroupLocalServiceUtil.getGroup(
186                                    user.getCompanyId(), GroupConstants.GUEST);
187    
188                            groups.add(group);
189    
190                            return groups;
191                    }
192    
193                    // Communities
194    
195                    Set<Group> groups = new HashSet<Group>();
196    
197                    LinkedHashMap<String, Object> params =
198                            new LinkedHashMap<String, Object>();
199    
200                    params.put("usersGroups", user.getUserId());
201    
202                    OrderByComparator<Group> orderByComparator =
203                            new GroupFriendlyURLComparator(true);
204    
205                    groups.addAll(
206                            GroupLocalServiceUtil.search(
207                                    user.getCompanyId(), null, null, params, QueryUtil.ALL_POS,
208                                    QueryUtil.ALL_POS, orderByComparator));
209    
210                    // Organizations
211    
212                    groups.addAll(
213                            GroupLocalServiceUtil.getUserOrganizationsGroups(
214                                    user.getUserId(), QueryUtil.ALL_POS, QueryUtil.ALL_POS));
215    
216                    // User
217    
218                    if (!user.isDefaultUser()) {
219                            groups.add(user.getGroup());
220                    }
221    
222                    List<Group> groupsList = new ArrayList<Group>(groups);
223    
224                    Collections.sort(groupsList, orderByComparator);
225    
226                    return groupsList;
227            }
228    
229            public static WebDAVUtil getInstance() {
230                    PortalRuntimePermission.checkGetBeanProperty(WebDAVUtil.class);
231    
232                    return _instance;
233            }
234    
235            public static String getLockUuid(HttpServletRequest request)
236                    throws WebDAVException {
237    
238                    String token = StringPool.BLANK;
239    
240                    String value = GetterUtil.getString(request.getHeader("If"));
241    
242                    if (_log.isDebugEnabled()) {
243                            _log.debug("\"If\" header is " + value);
244                    }
245    
246                    if (value.contains("(<DAV:no-lock>)")) {
247                            if (_log.isWarnEnabled()) {
248                                    _log.warn("Lock tokens can never be <DAV:no-lock>");
249                            }
250    
251                            throw new WebDAVException();
252                    }
253    
254                    int beg = value.indexOf(TOKEN_PREFIX);
255    
256                    if (beg >= 0) {
257                            beg += TOKEN_PREFIX.length();
258    
259                            if (beg < value.length()) {
260                                    int end = value.indexOf(CharPool.GREATER_THAN, beg);
261    
262                                    token = GetterUtil.getString(value.substring(beg, end));
263                            }
264                    }
265    
266                    return token;
267            }
268    
269            public static String[] getPathArray(String path) {
270                    return getPathArray(path, false);
271            }
272    
273            public static String[] getPathArray(String path, boolean fixTrailing) {
274                    path = HttpUtil.fixPath(path, true, fixTrailing);
275    
276                    return StringUtil.split(path, CharPool.SLASH);
277            }
278    
279            public static String getResourceName(String[] pathArray) {
280                    if (pathArray.length <= 2) {
281                            return StringPool.BLANK;
282                    }
283                    else {
284                            return pathArray[pathArray.length - 1];
285                    }
286            }
287    
288            public static WebDAVStorage getStorage(String token) {
289                    return getInstance()._getStorage(token);
290            }
291    
292            public static Collection<String> getStorageTokens() {
293                    return getInstance()._getStorageTokens();
294            }
295    
296            public static long getTimeout(HttpServletRequest request) {
297                    final String TIME_PREFIX = "Second-";
298    
299                    long timeout = 0;
300    
301                    String value = GetterUtil.getString(request.getHeader("Timeout"));
302    
303                    if (_log.isDebugEnabled()) {
304                            _log.debug("\"Timeout\" header is " + value);
305                    }
306    
307                    int index = value.indexOf(TIME_PREFIX);
308    
309                    if (index >= 0) {
310                            index += TIME_PREFIX.length();
311    
312                            if (index < value.length()) {
313                                    timeout = GetterUtil.getLong(value.substring(index));
314                            }
315                    }
316    
317                    return timeout * Time.SECOND;
318            }
319    
320            public static boolean isOverwrite(HttpServletRequest request) {
321                    return getInstance()._isOverwrite(request);
322            }
323    
324            public static String stripManualCheckInRequiredPath(String url) {
325                    return stripToken(url, DL.MANUAL_CHECK_IN_REQUIRED_PATH);
326            }
327    
328            public static String stripOfficeExtension(String url) {
329                    String strippedUrl = stripToken(url, DL.OFFICE_EXTENSION_PATH);
330    
331                    if (strippedUrl.length() != url.length()) {
332                            strippedUrl = FileUtil.stripExtension(strippedUrl);
333                    }
334    
335                    return strippedUrl;
336            }
337    
338            public static String stripToken(String url, String token) {
339                    if (Validator.isNull(url)) {
340                            return StringPool.BLANK;
341                    }
342    
343                    int index = url.indexOf(token);
344    
345                    if (index >= 0) {
346                            url =
347                                    url.substring(0, index) + url.substring(index + token.length());
348                    }
349    
350                    return url;
351            }
352    
353            private WebDAVUtil() {
354                    Registry registry = RegistryUtil.getRegistry();
355    
356                    _serviceTracker = registry.trackServices(
357                            WebDAVStorage.class, new WebDAVStorageServiceTrackerCustomizer());
358    
359                    _serviceTracker.open();
360            }
361    
362            private void _addStorage(WebDAVStorage storage) {
363                    Registry registry = RegistryUtil.getRegistry();
364    
365                    ServiceRegistration<WebDAVStorage> serviceRegistration =
366                            registry.registerService(WebDAVStorage.class, storage);
367    
368                    _serviceRegistrations.put(storage, serviceRegistration);
369            }
370    
371            private void _deleteStorage(WebDAVStorage storage) {
372                    ServiceRegistration<WebDAVStorage> serviceRegistration =
373                            _serviceRegistrations.remove(storage);
374    
375                    if (serviceRegistration != null) {
376                            serviceRegistration.unregister();
377                    }
378            }
379    
380            private WebDAVStorage _getStorage(String token) {
381                    return _storageMap.get(token);
382            }
383    
384            private Collection<String> _getStorageTokens() {
385                    return _storageMap.keySet();
386            }
387    
388            private boolean _isOverwrite(HttpServletRequest request) {
389                    String value = GetterUtil.getString(request.getHeader("Overwrite"));
390    
391                    if (StringUtil.equalsIgnoreCase(value, "F") ||
392                            !GetterUtil.getBoolean(value)) {
393    
394                            return false;
395                    }
396                    else {
397                            return true;
398                    }
399            }
400    
401            private static Log _log = LogFactoryUtil.getLog(WebDAVUtil.class);
402    
403            private static WebDAVUtil _instance = new WebDAVUtil();
404    
405            private ServiceRegistrationMap<WebDAVStorage> _serviceRegistrations =
406                    new ServiceRegistrationMap<WebDAVStorage>();
407            private ServiceTracker<WebDAVStorage, WebDAVStorage> _serviceTracker;
408            private Map<String, WebDAVStorage> _storageMap =
409                    new ConcurrentSkipListMap<String, WebDAVStorage>();
410    
411            private class WebDAVStorageServiceTrackerCustomizer
412                    implements ServiceTrackerCustomizer<WebDAVStorage, WebDAVStorage> {
413    
414                    @Override
415                    public WebDAVStorage addingService(
416                            ServiceReference<WebDAVStorage> serviceReference) {
417    
418                            Registry registry = RegistryUtil.getRegistry();
419    
420                            WebDAVStorage webDAVStorage = registry.getService(serviceReference);
421    
422                            if (webDAVStorage.getToken() == null) {
423                                    return null;
424                            }
425    
426                            _storageMap.put(webDAVStorage.getToken(), webDAVStorage);
427    
428                            return webDAVStorage;
429                    }
430    
431                    @Override
432                    public void modifiedService(
433                            ServiceReference<WebDAVStorage> serviceReference,
434                            WebDAVStorage webDAVStorage) {
435                    }
436    
437                    @Override
438                    public void removedService(
439                            ServiceReference<WebDAVStorage> serviceReference,
440                            WebDAVStorage webDAVStorage) {
441    
442                            Registry registry = RegistryUtil.getRegistry();
443    
444                            registry.ungetService(serviceReference);
445    
446                            _storageMap.remove(webDAVStorage.getToken());
447                    }
448    
449            }
450    
451    }