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