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