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 <iostream>
17 #include "fragment_metadata.h"
18 #include "image_log.h"
19 #include "image_utils.h"
20 #include "media_errors.h"
21 
22 #undef LOG_DOMAIN
23 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
24 
25 #undef LOG_TAG
26 #define LOG_TAG "FragmentMetadata"
27 
28 namespace OHOS {
29 namespace Media {
30 const static uint64_t MAX_FRAGMENT_MAP_META_COUNT = 10;
31 const static uint64_t MAX_FRAGMENT_MAP_META_LENGTH = 100;
FragmentMetadata()32 FragmentMetadata::FragmentMetadata() {}
33 
FragmentMetadata(const FragmentMetadata & fragmentMetadata)34 FragmentMetadata::FragmentMetadata(const FragmentMetadata& fragmentMetadata)
35 {
36     if (fragmentMetadata.properties_ != nullptr) {
37         properties_ = std::make_shared<ImageMetadata::PropertyMap>(*fragmentMetadata.properties_);
38     }
39 }
40 
~FragmentMetadata()41 FragmentMetadata::~FragmentMetadata() {}
42 
IsValidKey(const std::string & key)43 static bool IsValidKey(const std::string &key)
44 {
45     return FRAGMENT_METADATA_KEYS.find(key) != FRAGMENT_METADATA_KEYS.end();
46 }
47 
GetValue(const std::string & key,std::string & value) const48 int FragmentMetadata::GetValue(const std::string &key, std::string &value) const
49 {
50     if (properties_ == nullptr) {
51         IMAGE_LOGE("%{public}s properties is nullptr.", __func__);
52         return ERR_IMAGE_INVALID_PARAMETER;
53     }
54     if (!IsValidKey(key)) {
55         IMAGE_LOGE("Key is not supported.");
56         return ERR_IMAGE_INVALID_PARAMETER;
57     }
58     auto it = properties_->find(key);
59     if (it != properties_->end()) {
60         value = it->second;
61         return SUCCESS;
62     }
63     IMAGE_LOGE("key is not found in properties: %{public}s", key.c_str());
64     return ERR_IMAGE_INVALID_PARAMETER;
65 }
66 
SetValue(const std::string & key,const std::string & value)67 bool FragmentMetadata::SetValue(const std::string &key, const std::string &value)
68 {
69     if (!IsValidKey(key)) {
70         IMAGE_LOGE("Key is not supported.");
71         return false;
72     }
73     uint32_t casted;
74     if (!ImageUtils::StrToUint32(value, casted)) {
75         IMAGE_LOGE("Invalid value: %{public}s.", value.c_str());
76         return false;
77     }
78     if (properties_ == nullptr) {
79         IMAGE_LOGE("SetValue: properties_ is nullptr");
80         return false;
81     }
82     if (properties_->size() >= MAX_FRAGMENT_MAP_META_COUNT) {
83         IMAGE_LOGE("Failed to set value, the size of metadata properties exceeds the maximum limit %{public}llu.",
84             static_cast<unsigned long long>(MAX_FRAGMENT_MAP_META_COUNT));
85         return false;
86     }
87     if (key.length() > MAX_FRAGMENT_MAP_META_LENGTH || value.length() > MAX_FRAGMENT_MAP_META_LENGTH) {
88         IMAGE_LOGE("Failed to set value, the length of fragment string exceeds the maximum limit %{public}llu.",
89             static_cast<unsigned long long>(MAX_FRAGMENT_MAP_META_LENGTH));
90         return false;
91     }
92     (*properties_)[key] = value;
93     return true;
94 }
95 
RemoveEntry(const std::string & key)96 bool FragmentMetadata::RemoveEntry(const std::string &key)
97 {
98     if (properties_ == nullptr) {
99         IMAGE_LOGE("%{public}s properties is nullptr.", __func__);
100         return false;
101     }
102     if (!IsValidKey(key)) {
103         IMAGE_LOGE("Key is not supported.");
104         return false;
105     }
106     auto it = properties_->find(key);
107     if (it != properties_->end()) {
108         properties_->erase(it);
109         IMAGE_LOGD("RemoveEntry for key: %{public}s", key.c_str());
110         return true;
111     } else {
112         IMAGE_LOGE("RemoveEntry failed, key is not found in properties: %{public}s", key.c_str());
113         return false;
114     }
115 }
116 
GetAllProperties()117 const ImageMetadata::PropertyMapPtr FragmentMetadata::GetAllProperties()
118 {
119     return properties_;
120 }
121 
CloneMetadata()122 std::shared_ptr<ImageMetadata> FragmentMetadata::CloneMetadata()
123 {
124     if (properties_->size() > MAX_FRAGMENT_MAP_META_COUNT) {
125         IMAGE_LOGE("Failed to clone, the size of metadata properties exceeds the maximum limit %{public}llu.",
126             static_cast<unsigned long long>(MAX_FRAGMENT_MAP_META_COUNT));
127         return nullptr;
128     }
129     return std::make_shared<FragmentMetadata>(*this);
130 }
131 
Marshalling(Parcel & parcel) const132 bool FragmentMetadata::Marshalling(Parcel &parcel) const
133 {
134     if (properties_ == nullptr) {
135         IMAGE_LOGE("%{public}s properties is nullptr.", __func__);
136         return false;
137     }
138     if (properties_->size() > MAX_FRAGMENT_MAP_META_COUNT) {
139         IMAGE_LOGE("The number of metadata properties exceeds the maximum limit.");
140         return false;
141     }
142     if (!parcel.WriteUint64(properties_->size())) {
143         return false;
144     }
145     for (const auto &pair : *properties_) {
146         if (!IsValidKey(pair.first)) {
147             IMAGE_LOGE("The key of fragmentmetadata is invalid.");
148             return false;
149         }
150         uint32_t casted;
151         if (!ImageUtils::StrToUint32(pair.second, casted)) {
152             IMAGE_LOGE("The Value of fragmentmetadata is invalid.");
153             return false;
154         }
155         if (pair.first.length() > MAX_FRAGMENT_MAP_META_LENGTH || pair.second.length() > MAX_FRAGMENT_MAP_META_LENGTH) {
156             IMAGE_LOGE("The length of fragment string exceeds the maximum limit.");
157             return false;
158         }
159         if (!parcel.WriteString(pair.first)) {
160             return false;
161         }
162         if (!parcel.WriteString(pair.second)) {
163             return false;
164         }
165     }
166     return true;
167 }
168 
Unmarshalling(Parcel & parcel)169 FragmentMetadata *FragmentMetadata::Unmarshalling(Parcel &parcel)
170 {
171     PICTURE_ERR error;
172     FragmentMetadata* dstFragmentMetadata = FragmentMetadata::Unmarshalling(parcel, error);
173     if (dstFragmentMetadata == nullptr || error.errorCode != SUCCESS) {
174         IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
175             error.errorCode, error.errorInfo.c_str());
176     }
177     return dstFragmentMetadata;
178 }
179 
Unmarshalling(Parcel & parcel,PICTURE_ERR & error)180 FragmentMetadata *FragmentMetadata::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
181 {
182     std::unique_ptr<FragmentMetadata> fragmentMetadataPtr = std::make_unique<FragmentMetadata>();
183     uint64_t size;
184     if (!parcel.ReadUint64(size)) {
185         return nullptr;
186     }
187     if (size > MAX_FRAGMENT_MAP_META_COUNT) {
188         return nullptr;
189     }
190     if (fragmentMetadataPtr->properties_ == nullptr) {
191         IMAGE_LOGE("Unmarshalling: fragmentMetadataPtr->properties_ is nullptr");
192         return nullptr;
193     }
194     for (uint64_t i = 0; i < size; ++i) {
195         std::string key;
196         std::string value;
197         if (!parcel.ReadString(key)) {
198             return nullptr;
199         }
200         if (!parcel.ReadString(value)) {
201             return nullptr;
202         }
203         if (!IsValidKey(key)) {
204             IMAGE_LOGE("The key of fragmentmetadata is invalid.");
205             return nullptr;
206         }
207         uint32_t casted;
208         if (!ImageUtils::StrToUint32(value, casted)) {
209             IMAGE_LOGE("The Value of fragmentmetadata is invalid.");
210             return nullptr;
211         }
212         if (key.length() > MAX_FRAGMENT_MAP_META_LENGTH || value.length() > MAX_FRAGMENT_MAP_META_LENGTH) {
213             IMAGE_LOGE("The length of fragment string exceeds the maximum limit.");
214             return nullptr;
215         }
216         fragmentMetadataPtr->properties_->insert(std::make_pair(key, value));
217     }
218     return fragmentMetadataPtr.release();
219 }
220 
221 } // namespace Media
222 } // namespace OHOS