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 "box/item_info_box.h"
17 
18 namespace OHOS {
19 namespace ImagePlugin {
ParseContentChildren(HeifStreamReader & reader,uint32_t & recursionCount)20 heif_error HeifIinfBox::ParseContentChildren(HeifStreamReader &reader, uint32_t &recursionCount)
21 {
22     recursionCount++;
23     if (recursionCount > MAX_RECURSION_COUNT) {
24         return heif_error_too_many_recursion;
25     }
26     ParseFullHeader(reader);
27     uint8_t boxVersion = GetVersion();
28     uint32_t entryCount = (boxVersion == HEIF_BOX_VERSION_ZERO) ? reader.Read16() : reader.Read32();
29     if (entryCount == 0) {
30         return heif_error_ok;
31     }
32     return ReadChildren(reader, recursionCount);
33 }
34 
InferFullBoxVersion()35 void HeifIinfBox::InferFullBoxVersion()
36 {
37     SetVersion(children_.size() > 0xFFFF ? HEIF_BOX_VERSION_ONE : HEIF_BOX_VERSION_ZERO);
38 }
39 
Write(HeifStreamWriter & writer) const40 heif_error HeifIinfBox::Write(HeifStreamWriter &writer) const
41 {
42     size_t boxStart = ReserveHeader(writer);
43     uint8_t boxVersion = GetVersion();
44     writer.Write(boxVersion > HEIF_BOX_VERSION_ZERO ? UINT32_BYTES_NUM : UINT16_BYTES_NUM, children_.size());
45     heif_error err = WriteChildren(writer);
46     WriteCalculatedHeader(writer, boxStart);
47     return err;
48 }
49 
ParseContent(HeifStreamReader & reader)50 heif_error HeifInfeBox::ParseContent(HeifStreamReader &reader)
51 {
52     ParseFullHeader(reader);
53 
54     uint8_t boxVersion = GetVersion();
55     if (boxVersion <= HEIF_BOX_VERSION_ONE) {
56         itemId_ = reader.Read16();
57         itemProtectionIndex_ = reader.Read16();
58         itemName_ = reader.ReadString();
59         contentType_ = reader.ReadString();
60         contentEncoding_ = reader.ReadString();
61     } else if (boxVersion >= HEIF_BOX_VERSION_TWO) {
62         isHidden_ = (GetFlags() & 0x01);
63         itemId_ = boxVersion == HEIF_BOX_VERSION_TWO ? reader.Read16() : reader.Read32();
64         itemProtectionIndex_ = reader.Read16();
65         uint32_t itemType = reader.Read32();
66         if (itemType != 0) {
67             itemType_ = code_to_fourcc(itemType);
68         }
69         itemName_ = reader.ReadString();
70         if (itemType == ITEM_TYPE_MIME) {
71             contentType_ = reader.ReadString();
72             contentEncoding_ = reader.ReadString();
73         } else if (itemType == ITEM_TYPE_URI) {
74             itemUriType_ = reader.ReadString();
75         }
76     }
77 
78     return reader.GetError();
79 }
80 
InferFullBoxVersion()81 void HeifInfeBox::InferFullBoxVersion()
82 {
83     uint8_t version = GetVersion();
84     if (isHidden_ || !itemType_.empty()) {
85         version = std::max(version, (uint8_t)HEIF_BOX_VERSION_TWO);
86     }
87     if (itemId_ > 0xFFFF) {
88         version = std::max(version, (uint8_t)HEIF_BOX_VERSION_THREE);
89     }
90     SetVersion(version);
91 }
92 
SetHidden(bool hidden)93 void HeifInfeBox::SetHidden(bool hidden)
94 {
95     isHidden_ = hidden;
96     SetFlags(isHidden_ ? (GetFlags() | 0x01) : (GetFlags() & ~(0x00000001)));
97 }
98 
Write(HeifStreamWriter & writer) const99 heif_error HeifInfeBox::Write(HeifStreamWriter &writer) const
100 {
101     size_t boxStart = ReserveHeader(writer);
102 
103     uint8_t boxVersion = GetVersion();
104     if (boxVersion <= HEIF_BOX_VERSION_ONE) {
105         writer.Write16(itemId_);
106         writer.Write16(itemProtectionIndex_);
107 
108         writer.Write(itemName_);
109         writer.Write(contentType_);
110         writer.Write(contentEncoding_);
111     }
112 
113     if (boxVersion >= HEIF_BOX_VERSION_TWO) {
114         if (boxVersion == HEIF_BOX_VERSION_TWO) {
115             writer.Write16(itemId_);
116         } else if (boxVersion == HEIF_BOX_VERSION_THREE) {
117             writer.Write32(itemId_);
118         }
119 
120         writer.Write16(itemProtectionIndex_);
121 
122         if (itemType_.empty()) {
123             writer.Write32(0);
124         } else {
125             writer.Write32(fourcc_to_code(itemType_.c_str()));
126         }
127 
128         writer.Write(itemName_);
129         if (itemType_ == "mime") {
130             writer.Write(contentType_);
131             writer.Write(contentEncoding_);
132         } else if (itemType_ == "uri ") {
133             writer.Write(itemUriType_);
134         }
135     }
136 
137     WriteCalculatedHeader(writer, boxStart);
138     return heif_error_ok;
139 }
140 
ParseContent(HeifStreamReader & reader)141 heif_error HeifPtimBox::ParseContent(HeifStreamReader &reader)
142 {
143     ParseFullHeader(reader);
144     uint8_t boxVersion = GetVersion();
145     itemId_ = boxVersion == HEIF_BOX_VERSION_ZERO ? reader.Read16() : reader.Read32();
146     return reader.GetError();
147 }
148 
InferFullBoxVersion()149 void HeifPtimBox::InferFullBoxVersion()
150 {
151     SetVersion(itemId_ <= 0xFFFF ? HEIF_BOX_VERSION_ZERO : HEIF_BOX_VERSION_ONE);
152 }
153 
Write(HeifStreamWriter & writer) const154 heif_error HeifPtimBox::Write(HeifStreamWriter &writer) const
155 {
156     size_t boxStart = ReserveHeader(writer);
157 
158     if (GetVersion() == HEIF_BOX_VERSION_ZERO) {
159         writer.Write16(itemId_);
160     } else {
161         writer.Write32(itemId_);
162     }
163 
164     WriteCalculatedHeader(writer, boxStart);
165     return heif_error_ok;
166 }
167 } // namespace ImagePlugin
168 } // namespace OHOS
169