View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  package org.opencastproject.index.service.util;
22  
23  import org.opencastproject.list.api.ListProviderException;
24  import org.opencastproject.list.api.ListProvidersService;
25  import org.opencastproject.list.impl.ResourceListQueryImpl;
26  
27  import com.google.common.net.MediaType;
28  
29  import org.apache.commons.lang3.StringUtils;
30  import org.json.simple.JSONArray;
31  import org.json.simple.JSONObject;
32  import org.json.simple.parser.JSONParser;
33  import org.json.simple.parser.ParseException;
34  
35  import java.util.Arrays;
36  import java.util.Collection;
37  import java.util.List;
38  import java.util.ListIterator;
39  import java.util.Map;
40  import java.util.TreeMap;
41  import java.util.stream.Collectors;
42  
43  public final class RequestUtils {
44    public static final String ID_JSON_KEY = "id";
45    public static final String VALUE_JSON_KEY = "value";
46    public static final String REQUIRED_JSON_KEY = "required";
47    private static final JSONParser parser = new JSONParser();
48  
49    private RequestUtils() {
50    }
51  
52    /**
53     * Get a {@link Map} of metadata fields from a JSON array.
54     *
55     * @param json
56     *          The json input.
57     * @return A {@link Map} of the metadata fields ids and values.
58     * @throws ParseException
59     *           Thrown if the json is malformed.
60     */
61    public static Map<String, String> getKeyValueMap(String json) throws ParseException {
62      JSONArray updatedFields = (JSONArray) parser.parse(json);
63      Map<String, String> fieldMap = new TreeMap<String, String>();
64      JSONObject field;
65      @SuppressWarnings("unchecked")
66      ListIterator<Object> iterator = updatedFields.listIterator();
67      while (iterator.hasNext()) {
68        field = (JSONObject) iterator.next();
69        String id = field.get(ID_JSON_KEY) != null ? field.get(ID_JSON_KEY).toString() : "";
70        String value = field.get(VALUE_JSON_KEY) != null ? field.get(VALUE_JSON_KEY).toString() : "";
71        String requiredStr = field.get(REQUIRED_JSON_KEY) != null ? field.get(REQUIRED_JSON_KEY).toString() : "false";
72        boolean required = Boolean.parseBoolean(requiredStr);
73  
74        if (StringUtils.trimToNull(id) != null && (StringUtils.trimToNull(value) != null || !required)) {
75          fieldMap.put(id, value);
76        } else {
77          throw new IllegalArgumentException(String.format(
78                  "One of the metadata fields is missing an id or value. The id was '%s' and the value was '%s'.", id,
79                  value));
80        }
81      }
82      return fieldMap;
83    }
84  
85    /**
86     * Check if an uploaded asset conforms to the configured list of accepted file types.
87     *
88     * @param assetUploadId
89     *          The id of the uploaded asset
90     * @param mediaType
91     *          The media type sent by the browser
92     * @param listProvidersService
93     *          The ListProviderService to get the configured accepted types from
94     *
95     * @return true if the given mediatype is accepted, false otherwise.
96     */
97    public static boolean typeIsAccepted(String fileName, String assetUploadId, MediaType mediaType,
98            ListProvidersService listProvidersService) {
99      if (mediaType.is(MediaType.OCTET_STREAM)) {
100       // No detailed info, so we have to accept...
101       return true;
102     }
103 
104     // get file extension with .
105     String fileExtension = null;
106     int dot = fileName.lastIndexOf('.');
107     if (dot != -1) {
108       fileExtension = fileName.substring(dot);
109     }
110 
111     try {
112       final Collection<String> assetUploadJsons = listProvidersService.getList("eventUploadAssetOptions",
113           new ResourceListQueryImpl(),false).values();
114       for (String assetUploadJson: assetUploadJsons) {
115         if (!assetUploadJson.startsWith("{") || !assetUploadJson.endsWith("}")) {
116           // Ignore non-json-values
117           continue;
118         }
119         @SuppressWarnings("unchecked")
120         final Map<String, String> assetUpload = (Map<String, String>) parser.parse(assetUploadJson);
121         if (assetUploadId.equals(assetUpload.get("id"))) {
122           final List<String> accepts = Arrays.stream(assetUpload.getOrDefault("accept", "*/*").split(","))
123               .map(String::trim).collect(Collectors.toList());
124           for (String accept : accepts) {
125             if (accept.contains("/") && mediaType.is(MediaType.parse(accept))) {
126               return true;
127             } else if (fileExtension != null && accept.contains(".") && fileExtension.equalsIgnoreCase(accept)) {
128               return true;
129             }
130           }
131           return false;
132         }
133       }
134     } catch (ListProviderException e) {
135       throw new IllegalArgumentException("Invalid assetUploadId: " + assetUploadId);
136     } catch (org.json.simple.parser.ParseException e) {
137       throw new IllegalStateException("cannot parse json list provider for asset upload Id " + assetUploadId, e);
138     }
139     throw new IllegalArgumentException("Invalid assetUploadId: " + assetUploadId);
140   }
141 
142 }