1 /*
2 * Copyright (C) 2023-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 #include <sstream>
16
17 #include "media_file_utils.h"
18 #include "media_log.h"
19 #include "medialibrary_errno.h"
20 #include "media_file_uri.h"
21 #include "medialibrary_helper_container.h"
22 #include "medialibrary_type_const.h"
23 #include "photo_album_column.h"
24 #include "string_ex.h"
25 #include "userfilemgr_uri.h"
26
27 using namespace std;
28 namespace OHOS {
29 namespace Media {
30 const size_t LEAST_PATH_LENGTH = 2;
31 const size_t BATCH_SIZE_START_AND_END = 2;
32 const std::string MEDIA_FILE_ID_DEFAULT = "-1";
33
34 const int ASSET_IN_BUCKET_NUM_MAX = 1000;
35 const int ASSET_DIR_START_NUM = 16;
36 const int ASSET_MAX_NUM = 10000000;
37
SolveMediaTypeV9(MediaType mediaType)38 static std::string SolveMediaTypeV9(MediaType mediaType)
39 {
40 switch (mediaType) {
41 case MEDIA_TYPE_AUDIO:
42 return MEDIALIBRARY_TYPE_AUDIO_URI;
43 case MEDIA_TYPE_VIDEO:
44 return MEDIALIBRARY_TYPE_VIDEO_URI;
45 case MEDIA_TYPE_IMAGE:
46 return MEDIALIBRARY_TYPE_IMAGE_URI;
47 case MEDIA_TYPE_FILE:
48 default:
49 return MEDIALIBRARY_TYPE_FILE_URI;
50 }
51 }
52
SolveMediaTypeV10(MediaType mediaType)53 static std::string SolveMediaTypeV10(MediaType mediaType)
54 {
55 switch (mediaType) {
56 case MEDIA_TYPE_AUDIO:
57 return AudioColumn::AUDIO_TYPE_URI;
58 case MEDIA_TYPE_VIDEO:
59 case MEDIA_TYPE_IMAGE:
60 return PhotoColumn::PHOTO_TYPE_URI;
61 case MEDIA_TYPE_FILE:
62 default:
63 return MEDIALIBRARY_TYPE_FILE_URI;
64 }
65 }
66
SolveMediaType(MediaType mediaType)67 static std::string SolveMediaType(MediaType mediaType)
68 {
69 switch (mediaType) {
70 case MEDIA_TYPE_AUDIO:
71 return MEDIALIBRARY_TYPE_AUDIO_URI;
72 case MEDIA_TYPE_VIDEO:
73 return MEDIALIBRARY_TYPE_VIDEO_URI;
74 case MEDIA_TYPE_IMAGE:
75 return MEDIALIBRARY_TYPE_IMAGE_URI;
76 case MEDIA_TYPE_ALBUM:
77 return MEDIALIBRARY_TYPE_ALBUM_URI;
78 case MEDIA_TYPE_SMARTALBUM:
79 return MEDIALIBRARY_TYPE_SMART_URI;
80 case MEDIA_TYPE_FILE:
81 default:
82 return MEDIALIBRARY_TYPE_FILE_URI;
83 }
84 }
85
ParseUri(const string & uri)86 void MediaFileUri::ParseUri(const string &uri)
87 {
88 if (MediaFileUtils::StartsWith(uri, PhotoColumn::PHOTO_URI_PREFIX)) {
89 uriType_ = API10_PHOTO_URI;
90 } else if (MediaFileUtils::StartsWith(uri, PhotoAlbumColumns::ALBUM_URI_PREFIX)) {
91 uriType_ = API10_PHOTOALBUM_URI;
92 } else if (MediaFileUtils::StartsWith(uri, AudioColumn::AUDIO_URI_PREFIX)) {
93 uriType_ = API10_AUDIO_URI;
94 } else if (MediaFileUtils::StartsWith(uri, PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX)) {
95 uriType_ = API10_ANALYSISALBUM_URI;
96 } else {
97 uriType_ = API9_URI;
98 }
99 }
100
GetMediaTypeUri(MediaType mediaType,const int32_t & apiVersion)101 std::string MediaFileUri::GetMediaTypeUri(MediaType mediaType, const int32_t &apiVersion)
102 {
103 switch (apiVersion) {
104 case MEDIA_API_VERSION_V9:
105 return SolveMediaTypeV9(mediaType);
106 case MEDIA_API_VERSION_V10:
107 return SolveMediaTypeV10(mediaType);
108 case MEDIA_API_VERSION_DEFAULT:
109 default:
110 return SolveMediaType(mediaType);
111 }
112 }
113
MediaFileUriConstruct(MediaType mediaType,const std::string & fileId,const std::string & networkId,const int32_t & apiVersion,const std::string & extrUri)114 std::string MediaFileUri::MediaFileUriConstruct(MediaType mediaType, const std::string &fileId,
115 const std::string &networkId, const int32_t &apiVersion, const std::string &extrUri)
116 {
117 std::string uri = ML_FILE_URI_PREFIX;
118 uri += GetMediaTypeUri(mediaType, apiVersion);
119 if (!fileId.empty()) {
120 uri += "/" + fileId;
121 }
122
123 if (!networkId.empty()) {
124 uri += ML_URI_NETWORKID_EQUAL + networkId;
125 }
126
127 if (apiVersion == MEDIA_API_VERSION_V10) {
128 uri += extrUri;
129 uri = MediaFileUtils::Encode(uri);
130 }
131 ParseUri(uri);
132 return uri;
133 }
134
SetQueryMap(MediaFileUri * uri,std::unordered_map<std::string,std::string> & queryMap)135 static void SetQueryMap(MediaFileUri* uri, std::unordered_map<std::string,
136 std::string> &queryMap)
137 {
138 // file://media/image/12?networkid=xxxx&api_version=xxxx
139 std::string query = uri->GetQuery();
140 std::string pairString;
141 std::stringstream queryStream(query);
142
143 while (getline(queryStream, pairString, '&')) {
144 size_t splitIndex = pairString.find('=');
145 if (splitIndex == std::string::npos || splitIndex == (pairString.length() - 1)) {
146 MEDIA_ERR_LOG("failed to parse query, query field is %{private}s!", pairString.c_str());
147 continue;
148 }
149 queryMap[pairString.substr(0, splitIndex)] = pairString.substr(splitIndex + 1);
150 }
151 return;
152 }
153
CalNetworkId(MediaFileUri * uri,std::unordered_map<std::string,std::string> queryMap)154 static std::string CalNetworkId(MediaFileUri* uri, std::unordered_map<std::string,
155 std::string> queryMap)
156 {
157 std::string scheme = uri->GetScheme();
158 if (scheme == ML_FILE_SCHEME) {
159 if (queryMap.find(ML_URI_NETWORKID) != queryMap.end()) {
160 return queryMap[ML_URI_NETWORKID];
161 }
162 return "";
163 } else if (scheme == ML_DATA_SHARE_SCHEME) {
164 return uri->GetAuthority();
165 }
166 MEDIA_DEBUG_LOG("CalNetworkId scheme is invalid, scheme is %{private}s", scheme.c_str());
167 return "";
168 }
169
GetNetworkId()170 const std::string& MediaFileUri::GetNetworkId()
171 {
172 if (this->networkId_ != MEDIA_FILE_URI_EMPTY) {
173 return this->networkId_;
174 }
175 SetQueryMap(this, this->queryMap_);
176 this->networkId_ = CalNetworkId(this, this->queryMap_);
177 return this->networkId_;
178 }
179
ParsePathWithExtrPara(std::string & path)180 static void ParsePathWithExtrPara(std::string &path)
181 {
182 auto index = path.rfind('/');
183 if (index == std::string::npos) {
184 MEDIA_ERR_LOG("find split for last string failed, %{private}s", path.c_str());
185 return;
186 }
187 auto lastStr = path.substr(index + 1);
188 auto uriTempNext = path.substr(0, index);
189 index = uriTempNext.rfind('/');
190 if (index == std::string::npos) {
191 MEDIA_ERR_LOG("find split for next string failed %{private}s", uriTempNext.c_str());
192 return;
193 }
194 auto preStr = uriTempNext.substr(index + 1);
195 if (lastStr.find('.') != std::string::npos) {
196 if (!all_of(preStr.begin(), preStr.end(), ::isdigit)) {
197 path = uriTempNext.substr(0, index);
198 return;
199 }
200 preStr = uriTempNext.substr(0, index);
201 index = preStr.rfind('/');
202 if (index == std::string::npos) {
203 path = uriTempNext;
204 return;
205 }
206 path = preStr;
207 }
208 }
209
CalFileId(MediaFileUri * uri)210 static std::string CalFileId(MediaFileUri* uri)
211 {
212 std::string path = uri->GetPath();
213 if (uri->IsApi10()) {
214 ParsePathWithExtrPara(path);
215 }
216
217 if (path.length() < LEAST_PATH_LENGTH) {
218 MEDIA_ERR_LOG("path is too short, path is %{private}s", path.c_str());
219 return MEDIA_FILE_ID_DEFAULT;
220 }
221
222 std::size_t index = path.rfind("/");
223 if (index == std::string::npos || index == path.length() - 1) {
224 MEDIA_ERR_LOG("failed to rfind /, path is %{private}s", path.c_str());
225 return MEDIA_FILE_ID_DEFAULT;
226 }
227
228 std::string fileId = path.substr(index + 1);
229 if (!std::all_of(fileId.begin(), fileId.end(), ::isdigit)) {
230 MEDIA_DEBUG_LOG("fileId is not all digit, fileId is %{private}s", fileId.c_str());
231 return MEDIA_FILE_ID_DEFAULT;
232 }
233
234 return fileId;
235 }
236
GetFileId()237 std::string MediaFileUri::GetFileId()
238 {
239 if (this->fileId_ != MEDIA_FILE_URI_EMPTY) {
240 return this->fileId_;
241 }
242 this->fileId_ = CalFileId(this);
243 return this->fileId_;
244 }
245
GetTableName()246 std::string MediaFileUri::GetTableName()
247 {
248 static std::map<std::string, std::string> tableNameMap = {
249 { MEDIALIBRARY_TYPE_IMAGE_URI, PhotoColumn::PHOTOS_TABLE },
250 { MEDIALIBRARY_TYPE_VIDEO_URI, PhotoColumn::PHOTOS_TABLE },
251 { MEDIALIBRARY_TYPE_AUDIO_URI, AudioColumn::AUDIOS_TABLE },
252 { MEDIALIBRARY_TYPE_FILE_URI, MEDIALIBRARY_TABLE },
253 { AudioColumn::AUDIO_TYPE_URI, AudioColumn::AUDIOS_TABLE },
254 { PhotoColumn::PHOTO_TYPE_URI, PhotoColumn::PHOTOS_TABLE }
255 };
256
257 std::string uriString = ToString();
258 size_t questionPosition = uriString.find_first_of('?');
259 if (questionPosition != string::npos) {
260 uriString = uriString.substr(0, questionPosition);
261 }
262
263 for (const auto &iter : tableNameMap) {
264 if (uriString.find(iter.first) != std::string::npos) {
265 return iter.second;
266 }
267 }
268 return "";
269 }
270
GetFilePath()271 std::string MediaFileUri::GetFilePath()
272 {
273 /* get helper */
274 std::shared_ptr<DataShare::DataShareHelper> dataShareHelper =
275 MediaLibraryHelperContainer::GetInstance()->GetDataShareHelper();
276 if (dataShareHelper == nullptr) {
277 MEDIA_ERR_LOG("get data share helper err");
278 return "";
279 }
280
281 DataShare::DatashareBusinessError error;
282 const std::string uriString = ToString();
283 std::string queryUri(UFM_QUERY_PHOTO);
284 DataShare::DataSharePredicates predicates;
285 std::vector<std::string> columns;
286 /* check api version */
287 if (uriString.find(PhotoColumn::PHOTO_TYPE_URI) != std::string::npos) {
288 predicates.EqualTo(MediaColumn::MEDIA_ID, GetFileId());
289 columns.emplace_back(MediaColumn::MEDIA_FILE_PATH);
290 MediaFileUtils::UriAppendKeyValue(queryUri, URI_PARAM_API_VERSION);
291 } else {
292 predicates.EqualTo(MEDIA_DATA_DB_ID, GetFileId());
293 columns.emplace_back(MEDIA_DATA_DB_FILE_PATH);
294 }
295 Uri uri(queryUri);
296 /* query and check */
297 auto resultSet = dataShareHelper->Query(uri, predicates, columns, &error);
298 int32_t ret = error.GetCode();
299 if (ret != 0) {
300 MEDIA_ERR_LOG("data share query err %{public}d", ret);
301 return "";
302 }
303 int32_t rowCount;
304 ret = resultSet->GetRowCount(rowCount);
305 if (ret != 0) {
306 MEDIA_ERR_LOG("result set get row count err %{public}d", ret);
307 return "";
308 }
309 if (rowCount != 1) {
310 MEDIA_ERR_LOG("more than one record");
311 return "";
312 }
313
314 /* get val */
315 ret = resultSet->GoToNextRow();
316 if (ret != 0) {
317 MEDIA_ERR_LOG("result set go to next row err %{public}d", ret);
318 return "";
319 }
320 std::string val;
321 ret = resultSet->GetString(0, val);
322 if (ret != 0) {
323 MEDIA_ERR_LOG("result set get string err %{public}d", ret);
324 return "";
325 }
326 return val;
327 }
328
IsValid()329 bool MediaFileUri::IsValid()
330 {
331 std::string scheme = this->GetScheme();
332 if (scheme != ML_FILE_SCHEME &&
333 scheme != ML_DATA_SHARE_SCHEME) {
334 MEDIA_ERR_LOG("scheme is invalid, uri is %{private}s", this->ToString().c_str());
335 return false;
336 }
337
338 if (this->GetAuthority() != ML_URI_AUTHORITY &&
339 this->GetPath().find(MEDIALIBRARY_DATA_URI_IDENTIFIER) != 0) {
340 MEDIA_ERR_LOG("failed to find /media, uri is %{private}s", this->ToString().c_str());
341 return false;
342 }
343
344 std::string fileId = this->GetFileId();
345 if (fileId == MEDIA_FILE_ID_DEFAULT) {
346 MEDIA_ERR_LOG("fileid is invaild, uri is %{private}s", this->ToString().c_str());
347 return false;
348 }
349
350 return true;
351 }
352
GetQueryKeys()353 std::unordered_map<std::string, std::string> &MediaFileUri::GetQueryKeys()
354 {
355 if (queryMap_.empty()) {
356 SetQueryMap(this, this->queryMap_);
357 }
358 return queryMap_;
359 }
360
IsApi10()361 bool MediaFileUri::IsApi10()
362 {
363 if ((ToString().find(PhotoColumn::PHOTO_TYPE_URI) != std::string::npos) ||
364 (ToString().find(AudioColumn::AUDIO_TYPE_URI) != std::string::npos) ||
365 (ToString().find(PhotoColumn::HIGHTLIGHT_COVER_URI) != std::string::npos)) {
366 return true;
367 }
368 return false;
369 }
370
GetUriType()371 int MediaFileUri::GetUriType()
372 {
373 return uriType_;
374 }
375
GetMediaTypeFromUri(const std::string & uri)376 MediaType MediaFileUri::GetMediaTypeFromUri(const std::string &uri)
377 {
378 if (MediaFileUtils::StartsWith(uri, PhotoColumn::PHOTO_URI_PREFIX)) {
379 return MEDIA_TYPE_PHOTO;
380 } else if (MediaFileUtils::StartsWith(uri, AudioColumn::AUDIO_URI_PREFIX)) {
381 return MEDIA_TYPE_AUDIO;
382 } else if (MediaFileUtils::StartsWith(uri, PhotoAlbumColumns::ALBUM_URI_PREFIX)) {
383 return Media::MEDIA_TYPE_ALBUM;
384 } else if (MediaFileUtils::StartsWith(uri, AUDIO_URI_PREFIX)) {
385 return Media::MEDIA_TYPE_AUDIO;
386 } else if (MediaFileUtils::StartsWith(uri, VIDEO_URI_PREFIX)) {
387 return Media::MEDIA_TYPE_VIDEO;
388 } else if (MediaFileUtils::StartsWith(uri, IMAGE_URI_PREFIX)) {
389 return Media::MEDIA_TYPE_IMAGE;
390 } else if (MediaFileUtils::StartsWith(uri, ALBUM_URI_PREFIX)) {
391 return Media::MEDIA_TYPE_ALBUM;
392 } else if (MediaFileUtils::StartsWith(uri, FILE_URI_PREFIX)) {
393 return Media::MEDIA_TYPE_FILE;
394 } else if (MediaFileUtils::StartsWith(uri, HIGHLIGHT_URI_PREFIX)) {
395 return Media::MEDIA_TYPE_FILE;
396 }
397 return Media::MEDIA_TYPE_DEFAULT;
398 }
399
RemoveAllFragment(std::string & uri)400 void MediaFileUri::RemoveAllFragment(std::string &uri)
401 {
402 size_t fragIndex = uri.find_first_of('#');
403 if (fragIndex != std::string::npos) {
404 uri = uri.substr(0, fragIndex);
405 }
406 }
407
UriValidCheck(Uri & uri)408 static int32_t UriValidCheck(Uri &uri)
409 {
410 std::string scheme = uri.GetScheme();
411 if (scheme != ML_FILE_SCHEME && scheme != ML_DATA_SHARE_SCHEME) {
412 MEDIA_ERR_LOG("scheme is invalid, uri is %{private}s", uri.ToString().c_str());
413 return E_INVALID_URI;
414 }
415
416 if (uri.GetAuthority() != ML_URI_AUTHORITY && uri.GetPath().find(MEDIALIBRARY_DATA_URI_IDENTIFIER) != 0) {
417 MEDIA_ERR_LOG("failed to find /media, uri is %{private}s", uri.ToString().c_str());
418 return E_INVALID_URI;
419 }
420 return E_OK;
421 }
422
HandleOldUriPath(std::string & path)423 static inline void HandleOldUriPath(std::string &path)
424 {
425 // Handle datashare:///media and datashare:///media/file_operation case
426 if (MediaFileUtils::StartsWith(path, MEDIALIBRARY_DATA_URI_IDENTIFIER)) {
427 path = path.substr(MEDIALIBRARY_DATA_URI_IDENTIFIER.size());
428 return;
429 }
430 }
431
RemovePrecedSlash(std::string & path)432 static inline void RemovePrecedSlash(std::string &path)
433 {
434 if (MediaFileUtils::StartsWith(path, SLASH_STR)) {
435 path = path.substr(SLASH_STR.size());
436 }
437 }
438
GetValidPath(Uri & uri,std::string & path)439 static void GetValidPath(Uri &uri, std::string &path)
440 {
441 if (UriValidCheck(uri) < 0) {
442 path = "";
443 return;
444 }
445
446 path = uri.GetPath();
447 HandleOldUriPath(path);
448 RemovePrecedSlash(path);
449 }
450
GetPathFirstDentry(Uri & uri)451 std::string MediaFileUri::GetPathFirstDentry(Uri &uri)
452 {
453 std::string path;
454 GetValidPath(uri, path);
455 // Example: file:://media/photo_operation/query, return the "photo_operation" part
456 return path.substr(0, path.find_first_of('/'));
457 }
458
GetPathSecondDentry(Uri & uri)459 std::string MediaFileUri::GetPathSecondDentry(Uri &uri)
460 {
461 std::string ret;
462 std::string firstDentry = GetPathFirstDentry(uri);
463 if (firstDentry.empty()) {
464 return ret;
465 }
466 std::string path;
467 GetValidPath(uri, path);
468 if (path.size() < firstDentry.size() + 1) {
469 return ret;
470 }
471 // Example: file:://media/photo_operation/query, return the "query" part
472 return path.substr(firstDentry.size() + 1);
473 }
474
GetPhotoId(const std::string & uri)475 std::string MediaFileUri::GetPhotoId(const std::string &uri)
476 {
477 if (!MediaFileUtils::StartsWith(uri, PhotoColumn::PHOTO_URI_PREFIX)) {
478 return "";
479 }
480 std::string tmp = uri.substr(PhotoColumn::PHOTO_URI_PREFIX.size());
481 return tmp.substr(0, tmp.find_first_of('/'));
482 }
483
GetTimeIdFromUri(const std::vector<std::string> & uriBatch,std::vector<std::string> & timeIdBatch)484 void MediaFileUri::GetTimeIdFromUri(const std::vector<std::string> &uriBatch, std::vector<std::string> &timeIdBatch)
485 {
486 for (size_t i = 0; i < uriBatch.size(); ++i) {
487 std::string uri = uriBatch.at(i);
488 if (uri.empty()) {
489 continue;
490 }
491 auto index = uri.rfind(ML_URI_TIME_ID);
492 if (index == std::string::npos) {
493 MEDIA_ERR_LOG("GetTimeIdFromUri find index for time_id failed: %{private}s", uri.c_str());
494 continue;
495 }
496 timeIdBatch.emplace_back(uri.substr(index + ML_URI_TIME_ID.length()));
497 }
498 }
499
GetTimeIdFromUri(const std::vector<std::string> & uriBatch,std::vector<std::string> & timeIdBatch,int32_t & start,int32_t & count)500 void MediaFileUri::GetTimeIdFromUri(const std::vector<std::string> &uriBatch, std::vector<std::string> &timeIdBatch,
501 int32_t &start, int32_t &count)
502 {
503 if (uriBatch.size() != BATCH_SIZE_START_AND_END) {
504 return;
505 }
506 std::vector<int32_t> offset;
507 for (size_t i = 0; i < uriBatch.size(); ++i) {
508 std::string uri = uriBatch.at(i);
509 if (uri.empty()) {
510 continue;
511 }
512 auto indexStart = uri.rfind(ML_URI_TIME_ID);
513 if (indexStart == std::string::npos) {
514 MEDIA_ERR_LOG("GetTimeIdFromUri find indexStart for time_id failed: %{private}s", uri.c_str());
515 continue;
516 }
517 auto indexEnd = uri.rfind(ML_URI_OFFSET);
518 if (indexEnd == std::string::npos) {
519 MEDIA_ERR_LOG("GetTimeIdFromUri find indexEnd for time_id failed: %{private}s", uri.c_str());
520 continue;
521 }
522 uint32_t timeIdLen = indexEnd - indexStart - ML_URI_TIME_ID.length();
523 if (indexEnd <= uri.size()) {
524 timeIdBatch.emplace_back(uri.substr(indexStart + ML_URI_TIME_ID.length(), timeIdLen));
525 }
526 if (indexEnd + ML_URI_OFFSET.length() <= uri.size()) {
527 offset.emplace_back(stoi(uri.substr(indexEnd + ML_URI_OFFSET.length())));
528 }
529 }
530 if (offset.size() != BATCH_SIZE_START_AND_END) {
531 return;
532 }
533 start = offset[0];
534 count = offset[1] - offset[0] + 1;
535 }
536
CreateAssetBucket(int32_t fileId,int32_t & bucketNum)537 int32_t MediaFileUri::CreateAssetBucket(int32_t fileId, int32_t &bucketNum)
538 {
539 if (fileId < 0) {
540 MEDIA_ERR_LOG("input fileId [%{public}d] is invalid", fileId);
541 return E_INVALID_FILEID;
542 }
543 fileId = fileId % ASSET_MAX_NUM;
544 int start = ASSET_DIR_START_NUM;
545 int divider = ASSET_DIR_START_NUM;
546 while (fileId > start * ASSET_IN_BUCKET_NUM_MAX) {
547 divider = start;
548 start *= 2; // 2: Left shift offset
549 }
550
551 int fileIdRemainder = fileId % divider;
552 if (fileIdRemainder == 0) {
553 bucketNum = start + fileIdRemainder;
554 } else {
555 bucketNum = (start - divider) + fileIdRemainder;
556 }
557 return E_OK;
558 }
559
GetPathFromUri(const string & uri,bool isPhoto)560 string MediaFileUri::GetPathFromUri(const string &uri, bool isPhoto)
561 {
562 size_t index = uri.rfind('/');
563 if (index == string::npos) {
564 MEDIA_ERR_LOG("index invalid %{private}s", uri.c_str());
565 return "";
566 }
567 string realTitle = uri.substr(0, index);
568 index = realTitle.rfind('/');
569 if (index == string::npos) {
570 MEDIA_ERR_LOG("invalid realTitle %{private}s", uri.c_str());
571 return "";
572 }
573 realTitle = realTitle.substr(index + 1);
574 index = realTitle.rfind('_');
575 if (index == string::npos) {
576 MEDIA_ERR_LOG("realTitle can not find _ %{private}s", uri.c_str());
577 return "";
578 }
579 string fileId = realTitle.substr(index + 1);
580 if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
581 MEDIA_ERR_LOG("fileId invalid %{private}s", uri.c_str());
582 return "";
583 }
584 int32_t fileUniqueId = 0;
585 if (!StrToInt(fileId, fileUniqueId)) {
586 MEDIA_ERR_LOG("invalid fileuri %{private}s", uri.c_str());
587 return "";
588 }
589 int32_t bucketNum = 0;
590 CreateAssetBucket(fileUniqueId, bucketNum);
591
592 string ext = MediaFileUtils::GetExtensionFromPath(uri);
593 if (ext.empty()) {
594 MEDIA_ERR_LOG("invalid ext %{private}s", uri.c_str());
595 return "";
596 }
597
598 string path = ROOT_MEDIA_DIR;
599 if (isPhoto) {
600 path += PHOTO_BUCKET + "/" + to_string(bucketNum) + "/" + realTitle + "." + ext;
601 } else {
602 path += AUDIO_BUCKET + "/" + to_string(bucketNum) + "/" + realTitle + "." + ext;
603 }
604 if (!MediaFileUtils::IsFileExists(path)) {
605 MEDIA_ERR_LOG("file not exist, path=%{private}s", path.c_str());
606 return "";
607 }
608 return path;
609 }
610
GetPhotoUri(const std::string & fileId,const std::string & path,const std::string & displayName)611 string MediaFileUri::GetPhotoUri(const std::string &fileId, const std::string &path, const std::string &displayName)
612 {
613 std::string uri = "";
614 CHECK_AND_RETURN_RET_LOG(!fileId.empty(), uri, "Failed to get fileId");
615 CHECK_AND_RETURN_RET_LOG(!path.empty(), uri, "Failed to get path");
616 CHECK_AND_RETURN_RET_LOG(!displayName.empty(), uri, "Failed to get displayName");
617
618 std::string tmpStr;
619 size_t lastSlashPos = path.find_last_of('/');
620 if (lastSlashPos != std::string::npos) {
621 tmpStr = path.substr(lastSlashPos + 1);
622 } else {
623 tmpStr = path;
624 }
625
626 std::string fileNameWithoutSuffix;
627 size_t lastDotPos = tmpStr.find_last_of('.');
628 if (lastDotPos!= std::string::npos) {
629 fileNameWithoutSuffix = tmpStr.substr(0, lastDotPos);
630 } else {
631 fileNameWithoutSuffix = tmpStr;
632 }
633
634 uri = PhotoColumn::PHOTO_URI_PREFIX + fileId + "/" + fileNameWithoutSuffix + "/" +displayName;
635 return uri;
636 }
637 } // namespace Media
638 } // namespace OHOS
639