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.document.library.kernel.util.DL;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.model.Group;
022    import com.liferay.portal.kernel.model.GroupConstants;
023    import com.liferay.portal.kernel.model.Portlet;
024    import com.liferay.portal.kernel.model.User;
025    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
026    import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
027    import com.liferay.portal.kernel.service.UserLocalServiceUtil;
028    import com.liferay.portal.kernel.util.CharPool;
029    import com.liferay.portal.kernel.util.FileUtil;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.HttpUtil;
032    import com.liferay.portal.kernel.util.OrderByComparator;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.StringUtil;
035    import com.liferay.portal.kernel.util.Time;
036    import com.liferay.portal.kernel.util.Validator;
037    import com.liferay.portal.kernel.util.comparator.GroupFriendlyURLComparator;
038    import com.liferay.portal.kernel.xml.Namespace;
039    import com.liferay.portal.kernel.xml.SAXReaderUtil;
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.ServiceTrackerCollections;
048    import com.liferay.registry.collections.ServiceTrackerMap;
049    
050    import java.util.ArrayList;
051    import java.util.Collection;
052    import java.util.Collections;
053    import java.util.HashSet;
054    import java.util.LinkedHashMap;
055    import java.util.List;
056    import java.util.Set;
057    
058    import javax.servlet.http.HttpServletRequest;
059    
060    /**
061     * @author Brian Wing Shun Chan
062     * @author Alexander Chow
063     * @author Raymond Aug??
064     */
065    public class WebDAVUtil {
066    
067            public static final Namespace DAV_URI = SAXReaderUtil.createNamespace(
068                    "D", "DAV:");
069    
070            public static final int SC_LOCKED = 423;
071    
072            public static final int SC_MULTI_STATUS = 207;
073    
074            public static final String TOKEN_PREFIX = "opaquelocktoken:";
075    
076            public static void addStorage(WebDAVStorage storage) {
077                    getInstance()._addStorage(storage);
078            }
079    
080            public static Namespace createNamespace(String prefix, String uri) {
081                    Namespace namespace = null;
082    
083                    if (uri.equals(WebDAVUtil.DAV_URI.getURI())) {
084                            namespace = WebDAVUtil.DAV_URI;
085                    }
086                    else if (Validator.isNull(prefix)) {
087                            namespace = SAXReaderUtil.createNamespace(uri);
088                    }
089                    else {
090                            namespace = SAXReaderUtil.createNamespace(prefix, uri);
091                    }
092    
093                    return namespace;
094            }
095    
096            public static void deleteStorage(WebDAVStorage storage) {
097                    getInstance()._deleteStorage(storage);
098            }
099    
100            public static long getDepth(HttpServletRequest request) {
101                    String value = GetterUtil.getString(request.getHeader("Depth"));
102    
103                    if (_log.isDebugEnabled()) {
104                            _log.debug("\"Depth\" header is " + value);
105                    }
106    
107                    if (value.equals("0")) {
108                            return 0;
109                    }
110                    else {
111                            return -1;
112                    }
113            }
114    
115            public static String getDestination(
116                    HttpServletRequest request, String rootPath) {
117    
118                    String headerDestination = request.getHeader("Destination");
119                    String[] pathSegments = StringUtil.split(headerDestination, rootPath);
120    
121                    String destination = pathSegments[pathSegments.length - 1];
122    
123                    destination = HttpUtil.decodePath(destination);
124    
125                    if (_log.isDebugEnabled()) {
126                            _log.debug("Destination " + destination);
127                    }
128    
129                    return destination;
130            }
131    
132            public static long getGroupId(long companyId, String path)
133                    throws WebDAVException {
134    
135                    String[] pathArray = getPathArray(path);
136    
137                    return getGroupId(companyId, pathArray);
138            }
139    
140            public static long getGroupId(long companyId, String[] pathArray)
141                    throws WebDAVException {
142    
143                    try {
144                            if (pathArray.length == 0) {
145                                    return 0;
146                            }
147    
148                            String name = pathArray[0];
149    
150                            Group group = GroupLocalServiceUtil.fetchFriendlyURLGroup(
151                                    companyId, StringPool.SLASH + name);
152    
153                            if (group != null) {
154                                    return group.getGroupId();
155                            }
156    
157                            User user = UserLocalServiceUtil.fetchUserByScreenName(
158                                    companyId, name);
159    
160                            if (user != null) {
161                                    group = user.getGroup();
162    
163                                    return group.getGroupId();
164                            }
165                    }
166                    catch (Exception e) {
167                            throw new WebDAVException(e);
168                    }
169    
170                    return 0;
171            }
172    
173            public static List<Group> getGroups(long userId) throws Exception {
174                    User user = UserLocalServiceUtil.getUser(userId);
175    
176                    return getGroups(user);
177            }
178    
179            public static List<Group> getGroups(User user) throws Exception {
180    
181                    // Guest
182    
183                    if (user.isDefaultUser()) {
184                            List<Group> groups = new ArrayList<>();
185    
186                            Group group = GroupLocalServiceUtil.getGroup(
187                                    user.getCompanyId(), GroupConstants.GUEST);
188    
189                            groups.add(group);
190    
191                            return groups;
192                    }
193    
194                    // Communities
195    
196                    Set<Group> groups = new HashSet<>();
197    
198                    LinkedHashMap<String, Object> params = new LinkedHashMap<>();
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<>(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 String getStorageToken(Portlet portlet) {
293                    WebDAVStorage webDAVStorageInstance =
294                            portlet.getWebDAVStorageInstance();
295    
296                    if (webDAVStorageInstance == null) {
297                            return null;
298                    }
299    
300                    return webDAVStorageInstance.getToken();
301            }
302    
303            public static Collection<String> getStorageTokens() {
304                    return getInstance()._getStorageTokens();
305            }
306    
307            public static long getTimeout(HttpServletRequest request) {
308                    long timeout = 0;
309    
310                    String value = GetterUtil.getString(request.getHeader("Timeout"));
311    
312                    if (_log.isDebugEnabled()) {
313                            _log.debug("\"Timeout\" header is " + value);
314                    }
315    
316                    int index = value.indexOf(_TIME_PREFIX);
317    
318                    if (index >= 0) {
319                            index += _TIME_PREFIX.length();
320    
321                            if (index < value.length()) {
322                                    timeout = GetterUtil.getLong(value.substring(index));
323                            }
324                    }
325    
326                    return timeout * Time.SECOND;
327            }
328    
329            public static boolean isOverwrite(HttpServletRequest request) {
330                    return getInstance()._isOverwrite(request);
331            }
332    
333            public static String stripManualCheckInRequiredPath(String url) {
334                    return stripToken(url, DL.MANUAL_CHECK_IN_REQUIRED_PATH);
335            }
336    
337            public static String stripOfficeExtension(String url) {
338                    String strippedUrl = stripToken(url, DL.OFFICE_EXTENSION_PATH);
339    
340                    if (strippedUrl.length() != url.length()) {
341                            strippedUrl = FileUtil.stripExtension(strippedUrl);
342                    }
343    
344                    return strippedUrl;
345            }
346    
347            public static String stripToken(String url, String token) {
348                    if (Validator.isNull(url)) {
349                            return StringPool.BLANK;
350                    }
351    
352                    int index = url.indexOf(token);
353    
354                    if (index >= 0) {
355                            url =
356                                    url.substring(0, index) + url.substring(index + token.length());
357                    }
358    
359                    return url;
360            }
361    
362            private WebDAVUtil() {
363                    _storages = ServiceTrackerCollections.openSingleValueMap(
364                            WebDAVStorage.class, "webdav.storage.token",
365                            new ServiceTrackerCustomizer<WebDAVStorage, WebDAVStorage>() {
366    
367                                    @Override
368                                    public WebDAVStorage addingService(
369                                            ServiceReference<WebDAVStorage> serviceReference) {
370    
371                                            Registry registry = RegistryUtil.getRegistry();
372    
373                                            WebDAVStorage webDAVStorage = registry.getService(
374                                                    serviceReference);
375    
376                                            setToken(serviceReference, webDAVStorage);
377    
378                                            return webDAVStorage;
379                                    }
380    
381                                    @Override
382                                    public void modifiedService(
383                                            ServiceReference<WebDAVStorage> serviceReference,
384                                            WebDAVStorage webDAVStorage) {
385    
386                                            setToken(serviceReference, webDAVStorage);
387                                    }
388    
389                                    @Override
390                                    public void removedService(
391                                            ServiceReference<WebDAVStorage> serviceReference,
392                                            WebDAVStorage webDAVStorage) {
393                                    }
394    
395                                    protected void setToken(
396                                            ServiceReference<WebDAVStorage> serviceReference,
397                                            WebDAVStorage webDAVStorage) {
398    
399                                            String token = (String)serviceReference.getProperty(
400                                                    "webdav.storage.token");
401    
402                                            webDAVStorage.setToken(token);
403                                    }
404    
405                            });
406            }
407    
408            private void _addStorage(WebDAVStorage storage) {
409                    Registry registry = RegistryUtil.getRegistry();
410    
411                    ServiceRegistration<WebDAVStorage> serviceRegistration =
412                            registry.registerService(WebDAVStorage.class, storage);
413    
414                    _serviceRegistrations.put(storage, serviceRegistration);
415            }
416    
417            private void _deleteStorage(WebDAVStorage storage) {
418                    ServiceRegistration<WebDAVStorage> serviceRegistration =
419                            _serviceRegistrations.remove(storage);
420    
421                    if (serviceRegistration != null) {
422                            serviceRegistration.unregister();
423                    }
424            }
425    
426            private WebDAVStorage _getStorage(String token) {
427                    return _storages.getService(token);
428            }
429    
430            private Collection<String> _getStorageTokens() {
431                    return _storages.keySet();
432            }
433    
434            private boolean _isOverwrite(HttpServletRequest request) {
435                    String value = GetterUtil.getString(request.getHeader("Overwrite"));
436    
437                    if (StringUtil.equalsIgnoreCase(value, "F") ||
438                            !GetterUtil.getBoolean(value)) {
439    
440                            return false;
441                    }
442                    else {
443                            return true;
444                    }
445            }
446    
447            private static final String _TIME_PREFIX = "Second-";
448    
449            private static final Log _log = LogFactoryUtil.getLog(WebDAVUtil.class);
450    
451            private static final WebDAVUtil _instance = new WebDAVUtil();
452    
453            private final ServiceRegistrationMap<WebDAVStorage> _serviceRegistrations =
454                    new ServiceRegistrationMapImpl<>();
455            private final ServiceTrackerMap<String, WebDAVStorage> _storages;
456    
457    }