1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ringtone_mimetype_utils.h"
17 
18 #include <fstream>
19 
20 #include "ringtone_log.h"
21 #include "ringtone_errno.h"
22 
23 namespace OHOS {
24 namespace Media {
25 using namespace std;
26 using namespace nlohmann;
27 
28 using MimeTypeMap = unordered_map<string, vector<string>>;
29 
30 MimeTypeMap RingtoneMimeTypeUtils::mediaJsonMap_;
31 const string MIMETYPE_JSON_PATH = "/system/etc/userfilemanager/userfilemanager_mimetypes.json";
32 const string DEFAULT_MIME_TYPE = "application/octet-stream";
33 
34 /**
35  * The format of the target json file:
36  * First floor: Media type string, such as image, video, audio, etc.
37  * Second floor: Mime type string
38  * Third floor: Extension array.
39 */
CreateMapFromJson()40 void RingtoneMimeTypeUtils::CreateMapFromJson()
41 {
42     std::ifstream jFile(MIMETYPE_JSON_PATH);
43     if (!jFile.is_open()) {
44         RINGTONE_ERR_LOG("Failed to open: %{private}s", MIMETYPE_JSON_PATH.c_str());
45         return;
46     }
47     json firstFloorObjs;
48     jFile >> firstFloorObjs;
49     for (auto& firstFloorObj : firstFloorObjs.items()) {
50         json secondFloorJsons = json::parse(firstFloorObj.value().dump(), nullptr, false);
51         if (secondFloorJsons.is_discarded()) {
52             continue;
53         }
54         for (auto &secondFloorJson : secondFloorJsons.items()) {
55             json thirdFloorJsons = json::parse(secondFloorJson.value().dump(), nullptr, false);
56             // Key: MimeType, Value: Extension array.
57             if (!thirdFloorJsons.is_discarded()) {
58                 mediaJsonMap_.insert(std::pair<string, vector<string>>(secondFloorJson.key(), thirdFloorJsons));
59             }
60         }
61     }
62 }
63 
InitMimeTypeMap()64 int32_t RingtoneMimeTypeUtils::InitMimeTypeMap()
65 {
66     CreateMapFromJson();
67     if (mediaJsonMap_.empty()) {
68         RINGTONE_ERR_LOG("JsonMap is empty");
69         return E_FAIL;
70     }
71     return E_OK;
72 }
73 
GetMimeTypeFromExtension(const string & extension)74 string RingtoneMimeTypeUtils::GetMimeTypeFromExtension(const string &extension)
75 {
76     return GetMimeTypeFromExtension(extension, mediaJsonMap_);
77 }
78 
GetMimeTypeFromExtension(const string & extension,const MimeTypeMap & mimeTypeMap)79 string RingtoneMimeTypeUtils::GetMimeTypeFromExtension(const string &extension,
80     const MimeTypeMap &mimeTypeMap)
81 {
82     string tmp = extension;
83     transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
84     for (auto &item : mimeTypeMap) {
85         for (auto &ext : item.second) {
86             if (ext == tmp) {
87                 return item.first;
88             }
89         }
90     }
91     return DEFAULT_MIME_TYPE;
92 }
93 
GetMediaTypeFromMimeType(const string & mimeType)94 RingtoneMediaType RingtoneMimeTypeUtils::GetMediaTypeFromMimeType(const string &mimeType)
95 {
96     size_t pos = mimeType.find_first_of("/");
97     if (pos == string::npos) {
98         RINGTONE_ERR_LOG("Invalid mime type: %{public}s", mimeType.c_str());
99         return RINGTONE_MEDIA_TYPE_INVALID;
100     }
101     string prefix = mimeType.substr(0, pos);
102     if (prefix == "audio") {
103         return RINGTONE_MEDIA_TYPE_AUDIO;
104     } else {
105         RINGTONE_ERR_LOG("Invalid mime type: %{public}s", mimeType.c_str());
106         return RINGTONE_MEDIA_TYPE_INVALID;
107     }
108 }
109 } // namespace Media
110 } // namespace OHOS
111