• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2023 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 #define MLOG_TAG "FileUtils"
16 
17 #include "media_file_utils.h"
18 
19 #include <algorithm>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <fstream>
23 #include <ftw.h>
24 #include <regex>
25 #include <sstream>
26 #include <sys/sendfile.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <unordered_map>
30 
31 #include "directory_ex.h"
32 #include "media_column.h"
33 #include "media_file_uri.h"
34 #include "media_log.h"
35 #include "medialibrary_db_const.h"
36 #include "medialibrary_errno.h"
37 #include "medialibrary_type_const.h"
38 #include "mimetype_utils.h"
39 #include "medialibrary_tracer.h"
40 
41 using namespace std;
42 
43 namespace OHOS::Media {
44 static const mode_t CHOWN_RWX_USR_GRP = 02771;
45 static const mode_t CHOWN_RW_USR_GRP = 0660;
46 constexpr size_t DISPLAYNAME_MAX = 255;
47 const int32_t OPEN_FDS = 64;
48 const std::string PATH_PARA = "path=";
49 constexpr size_t EMPTY_DIR_ENTRY_COUNT = 2;  // Empty dir has 2 entry: . and ..
50 
51 static const std::unordered_map<std::string, std::vector<std::string>> MEDIA_MIME_TYPE_MAP = {
52     { "application/epub+zip", { "epub" } },
53     { "application/lrc", { "lrc"} },
54     { "application/pkix-cert", { "cer" } },
55     { "application/rss+xml", { "rss" } },
56     { "application/sdp", { "sdp" } },
57     { "application/smil+xml", { "smil" } },
58     { "application/ttml+xml", { "ttml", "dfxp" } },
59     { "application/vnd.ms-pki.stl", { "stl" } },
60     { "application/vnd.ms-powerpoint", { "pot", "ppt" } },
61     { "application/vnd.ms-wpl", { "wpl" } },
62     { "application/vnd.stardivision.writer", { "vor" } },
63     { "application/vnd.youtube.yt", { "yt" } },
64     { "application/x-font", { "pcf" } },
65     { "application/x-mobipocket-ebook", { "prc", "mobi" } },
66     { "application/x-pem-file", { "pem" } },
67     { "application/x-pkcs12", { "p12", "pfx" } },
68     { "application/x-subrip", { "srt" } },
69     { "application/x-webarchive", { "webarchive" } },
70     { "application/x-webarchive-xml", { "webarchivexml" } },
71     { "application/pgp-signature", { "pgp" } },
72     { "application/x-x509-ca-cert", { "crt", "der" } },
73     { "application/json", { "json" } },
74     { "application/javascript", { "js" } },
75     { "application/zip", { "zip" } },
76     { "application/rar", { "rar" } },
77     { "application/pdf", { "pdf" } },
78     { "application/msword", { "doc" } },
79     { "application/ms-excel", { "xls" } },
80     { "application/vnd.openxmlformats-officedocument.wordprocessingml.document", { "docx" } },
81     { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", { "xlsx" } },
82     { "application/vnd.openxmlformats-officedocument.presentationml.presentation", { "pptx" } },
83     { "audio/3gpp", { "3ga" } },
84     { "audio/ac3", { "ac3", "a52"} },
85     { "audio/amr", { "amr" } },
86     { "audio/imelody", { "imy" } },
87     { "audio/midi", { "rtttl", "xmf", "rtx" } },
88     { "audio/mobile-xmf", { "mxmf"} },
89     { "audio/mp4", { "m4a", "m4b", "m4p", "f4a", "f4b", "f4p" } },
90     { "audio/mpegurl", { "m3u" } },
91     { "audio/sp-midi", { "smf" } },
92     { "audio/x-matroska", { "mka" } },
93     { "audio/x-pn-realaudio", { "ra" } },
94     { "audio/x-mpeg", { "mp3" } },
95     { "audio/aac", { "aac", "adts", "adt" } },
96     { "audio/basic", { "snd" } },
97     { "audio/flac", { "flac" } },
98     { "audio/mpeg", { "mp3", "mp2", "mp1", "mpa", "m4r" } },
99     { "audio/wav", { "wav" } },
100     { "audio/ogg", { "ogg" } },
101     { "image/gif", { "gif"} },
102     { "image/heic", { "heic" } },
103     { "image/heic-sequence", { "heics", "heifs" } },
104     { "image/bmp", { "bmp", "bm" } },
105     { "image/heif", { "heif", "hif" } },
106     { "image/avif", { "avif" } },
107     { "image/ico", { "cur" } },
108     { "image/webp", { "webp"} },
109     { "image/x-adobe-dng", { "dng" } },
110     { "image/x-fuji-raf", { "raf" } },
111     { "image/x-icon", { "ico" } },
112     { "image/x-nikon-nrw", { "nrw" } },
113     { "image/x-panasonic-rw2", { "rw2" } },
114     { "image/x-pentax-pef", { "pef" } },
115     { "image/x-samsung-srw", { "srw" } },
116     { "image/x-sony-arw", { "arw" } },
117     { "image/jpeg", { "jpg", "jpeg", "jpe" } },
118     { "image/png", { "png" } },
119     { "image/svg+xml", { "svg" } },
120     { "image/x-dcraw", { "raw" } },
121     { "video/3gpp2", { "3gpp2", "3gp2", "3g2" } },
122     { "video/3gpp", { "3gpp", "3gp" } },
123     { "video/avi", { "avi" } },
124     { "video/mp4", { "m4v", "f4v", "mp4v", "mpeg4", "mp4" }},
125     { "video/mp2t", { "m2ts", "mts"} },
126     { "video/mp2ts", { "ts" } },
127     { "video/vnd.youtube.yt", { "vt" } },
128     { "video/x-webex", { "wrf" } },
129     { "video/mpeg", { "mpeg", "mpeg2", "mpv2", "mp2v", "m2v", "m2t", "mpeg1", "mpv1", "mp1v", "m1v", "mpg" } },
130     { "video/quicktime", { "mov" } },
131     { "video/x-matroska", { "mkv" } },
132     { "video/webm", { "webm" } },
133     { "video/H264", { "h264" } },
134     { "text/comma-separated-values", { "csv" } },
135     { "text/plain", { "diff", "po", "txt" } },
136     { "text/rtf", { "rtf" } },
137     { "text/text", { "phps", "m3u", "m3u8" } },
138     { "text/xml", { "xml" } },
139     { "text/x-vcard", { "vcf" } },
140     { "text/x-c++hdr", { "hpp", "h++", "hxx", "hh" } },
141     { "text/x-c++src", { "cpp", "c++", "cxx", "cc" } },
142     { "text/css", { "css" } },
143     { "text/html", { "html", "htm", "shtml"} },
144     { "text/markdown", { "md", "markdown" } },
145     { "text/x-java", { "java" } },
146     { "text/x-python", { "py" } }
147 };
148 
UnlinkCb(const char * fpath,const struct stat * sb,int32_t typeflag,struct FTW * ftwbuf)149 int32_t UnlinkCb(const char *fpath, const struct stat *sb, int32_t typeflag, struct FTW *ftwbuf)
150 {
151     CHECK_AND_RETURN_RET_LOG(fpath != nullptr, E_FAIL, "fpath == nullptr");
152     int32_t errRet = remove(fpath);
153     if (errRet) {
154         MEDIA_ERR_LOG("Failed to remove errno: %{public}d, path: %{private}s", errno, fpath);
155     }
156 
157     return errRet;
158 }
159 
RemoveDirectory(const string & path)160 int32_t MediaFileUtils::RemoveDirectory(const string &path)
161 {
162     return nftw(path.c_str(), UnlinkCb, OPEN_FDS, FTW_DEPTH | FTW_PHYS);
163 }
164 
CreateDirectory(const string & dirPath)165 bool MediaFileUtils::CreateDirectory(const string &dirPath)
166 {
167     string subStr;
168     string segment;
169 
170     /*  Create directory and its sub directories if does not exist
171      *  take each string after '/' create directory if does not exist.
172      *  Created directory will be the base path for the next sub directory.
173      */
174 
175     stringstream folderStream(dirPath);
176     while (getline(folderStream, segment, '/')) {
177         if (segment.empty()) {    // skip the first "/" in case of "/storage/cloud/files"
178             continue;
179         }
180 
181         subStr.append(SLASH_CHAR + segment);
182         if (!IsDirectory(subStr)) {
183             mode_t mask = umask(0);
184             if (mkdir(subStr.c_str(), CHOWN_RWX_USR_GRP) == -1) {
185                 MEDIA_ERR_LOG("Failed to create directory %{public}d", errno);
186                 umask(mask);
187                 return false;
188             }
189             umask(mask);
190         }
191     }
192 
193     return true;
194 }
195 
IsFileExists(const string & fileName)196 bool MediaFileUtils::IsFileExists(const string &fileName)
197 {
198     struct stat statInfo {};
199 
200     return ((stat(fileName.c_str(), &statInfo)) == SUCCESS);
201 }
202 
IsDirEmpty(const string & path)203 bool MediaFileUtils::IsDirEmpty(const string &path)
204 {
205     DIR *dir = opendir(path.c_str());
206     if (dir == nullptr) {
207         MEDIA_ERR_LOG("Failed to open dir:%{private}s, errno: %{public}d. Just return dir NOT empty.",
208             path.c_str(), errno);
209         return false;
210     }
211     size_t entCount = 0;
212     while (readdir(dir) != nullptr) {
213         if (++entCount > EMPTY_DIR_ENTRY_COUNT) {
214             break;
215         }
216     }
217     if (closedir(dir) < 0) {
218         MEDIA_ERR_LOG("Fail to closedir: %{private}s, errno: %{public}d.", path.c_str(), errno);
219     }
220     return entCount <= EMPTY_DIR_ENTRY_COUNT;
221 }
222 
GetFileName(const string & filePath)223 string MediaFileUtils::GetFileName(const string &filePath)
224 {
225     string fileName;
226 
227     if (!(filePath.empty())) {
228         size_t lastSlash = filePath.rfind('/');
229         if (lastSlash != string::npos) {
230             if (filePath.size() > (lastSlash + 1)) {
231                 fileName = filePath.substr(lastSlash + 1);
232             }
233         }
234     }
235 
236     return fileName;
237 }
238 
IsDirectory(const string & dirName)239 bool MediaFileUtils::IsDirectory(const string &dirName)
240 {
241     struct stat statInfo {};
242     if (stat(dirName.c_str(), &statInfo) == SUCCESS) {
243         if (statInfo.st_mode & S_IFDIR) {
244             return true;
245         }
246     }
247 
248     return false;
249 }
250 
GetFirstDirName(const string & filePath)251 string MediaFileUtils::GetFirstDirName(const string &filePath)
252 {
253     string firstDirName = "";
254     if (!filePath.empty()) {
255         string::size_type pos = filePath.find_first_of('/');
256         if (pos == filePath.length()) {
257             return filePath;
258         }
259         firstDirName = filePath.substr(0, pos + 1);
260     }
261     return firstDirName;
262 }
263 
CreateFile(const string & filePath)264 bool MediaFileUtils::CreateFile(const string &filePath)
265 {
266     bool errCode = false;
267 
268     if (filePath.empty() || IsFileExists(filePath)) {
269         return errCode;
270     }
271 
272     ofstream file(filePath);
273     if (!file) {
274         MEDIA_ERR_LOG("Output file path could not be created");
275         return errCode;
276     }
277 
278     if (chmod(filePath.c_str(), CHOWN_RW_USR_GRP) == SUCCESS) {
279         errCode = true;
280     }
281 
282     file.close();
283 
284     return errCode;
285 }
286 
DeleteFile(const string & fileName)287 bool MediaFileUtils::DeleteFile(const string &fileName)
288 {
289     return (remove(fileName.c_str()) == SUCCESS);
290 }
291 
DeleteDir(const string & dirName)292 bool MediaFileUtils::DeleteDir(const string &dirName)
293 {
294     bool errRet = false;
295 
296     if (IsDirectory(dirName)) {
297         errRet = (RemoveDirectory(dirName) == SUCCESS);
298     }
299 
300     return errRet;
301 }
302 
MoveFile(const string & oldPath,const string & newPath)303 bool MediaFileUtils::MoveFile(const string &oldPath, const string &newPath)
304 {
305     bool errRet = false;
306 
307     if (IsFileExists(oldPath) && !IsFileExists(newPath)) {
308         errRet = (rename(oldPath.c_str(), newPath.c_str()) == SUCCESS);
309     }
310 
311     return errRet;
312 }
313 
CopyFileUtil(const string & filePath,const string & newPath)314 bool CopyFileUtil(const string &filePath, const string &newPath)
315 {
316     struct stat fst{};
317     bool errCode = false;
318     if (filePath.size() >= PATH_MAX) {
319         MEDIA_ERR_LOG("File path too long %{public}d", static_cast<int>(filePath.size()));
320         return errCode;
321     }
322     MEDIA_INFO_LOG("File path is %{private}s", filePath.c_str());
323     string absFilePath;
324     if (!PathToRealPath(filePath, absFilePath)) {
325         MEDIA_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
326         return errCode;
327     }
328     if (absFilePath.empty()) {
329         MEDIA_ERR_LOG("Failed to obtain the canonical path for source path%{private}s %{public}d",
330                       filePath.c_str(), errno);
331         return errCode;
332     }
333 
334     int32_t source = open(absFilePath.c_str(), O_RDONLY);
335     if (source == -1) {
336         MEDIA_ERR_LOG("Open failed for source file");
337         return errCode;
338     }
339 
340     int32_t dest = open(newPath.c_str(), O_WRONLY | O_CREAT, CHOWN_RWX_USR_GRP);
341     if (dest == -1) {
342         MEDIA_ERR_LOG("Open failed for destination file %{public}d", errno);
343         close(source);
344         return errCode;
345     }
346 
347     if (fstat(source, &fst) == SUCCESS) {
348         // Copy file content
349         if (sendfile(dest, source, nullptr, fst.st_size) != E_ERR) {
350             // Copy ownership and mode of source file
351             if (fchown(dest, fst.st_uid, fst.st_gid) == SUCCESS &&
352                 fchmod(dest, fst.st_mode) == SUCCESS) {
353                 errCode = true;
354             }
355         }
356     }
357 
358     close(source);
359     close(dest);
360 
361     return errCode;
362 }
363 
CopyFile(const string & filePath,const string & newPath)364 bool MediaFileUtils::CopyFile(const string &filePath, const string &newPath)
365 {
366     string newPathCorrected;
367     bool errCode = false;
368 
369     if (!(newPath.empty()) && !(filePath.empty())) {
370         newPathCorrected = newPath + "/" + GetFileName(filePath);
371     } else {
372         MEDIA_ERR_LOG("Src filepath or dest filePath value cannot be empty");
373         return false;
374     }
375 
376     if (IsFileExists(filePath) && !IsFileExists(newPathCorrected)) {
377         errCode = true; // set to create file if directory exists
378         if (!(IsDirectory(newPath))) {
379             errCode = CreateDirectory(newPath);
380         }
381         if (errCode) {
382             string canonicalDirPath;
383             if (!PathToRealPath(newPath, canonicalDirPath)) {
384                 MEDIA_ERR_LOG("Failed to obtain the canonical path for newpath %{private}s %{public}d",
385                               filePath.c_str(), errno);
386                 return false;
387             }
388             newPathCorrected = canonicalDirPath + "/" + GetFileName(filePath);
389             errCode = CopyFileUtil(filePath, newPathCorrected);
390         }
391     }
392 
393     return errCode;
394 }
395 
RenameDir(const string & oldPath,const string & newPath)396 bool MediaFileUtils::RenameDir(const string &oldPath, const string &newPath)
397 {
398     bool errRet = false;
399 
400     if (IsDirectory(oldPath)) {
401         errRet = (rename(oldPath.c_str(), newPath.c_str()) == SUCCESS);
402         if (!errRet) {
403             MEDIA_ERR_LOG("Failed RenameDir errno %{public}d", errno);
404         }
405     }
406 
407     return errRet;
408 }
409 
CheckStringSize(const string & str,const size_t max)410 int32_t MediaFileUtils::CheckStringSize(const string &str, const size_t max)
411 {
412     size_t size = str.length();
413     if (size == 0) {
414         return -EINVAL;
415     }
416     if (size > max) {
417         return -ENAMETOOLONG;
418     }
419     return E_OK;
420 }
421 
RegexCheck(const string & str,const string & regexStr)422 static inline bool RegexCheck(const string &str, const string &regexStr)
423 {
424     const regex express(regexStr);
425     return regex_search(str, express);
426 }
427 
CheckTitle(const string & title)428 static inline int32_t CheckTitle(const string &title)
429 {
430     static const string TITLE_REGEX_CHECK = R"([\.\\/:*?"'`<>|{}\[\]])";
431     if (RegexCheck(title, TITLE_REGEX_CHECK)) {
432         MEDIA_ERR_LOG("Failed to check title regex: %{private}s", title.c_str());
433         return -EINVAL;
434     }
435     return E_OK;
436 }
437 
438 int32_t MediaFileUtils::CheckDisplayName(const string &displayName)
439 {
440     int err = CheckStringSize(displayName, DISPLAYNAME_MAX);
441     if (err < 0) {
442         return err;
443     }
444     if (displayName.at(0) == '.') {
445         return -EINVAL;
446     }
447     string title = GetTitleFromDisplayName(displayName);
448     if (title.empty()) {
449         return -EINVAL;
450     }
451     return CheckTitle(title);
452 }
453 
454 int32_t MediaFileUtils::CheckFileDisplayName(const string &displayName)
455 {
456     int err = CheckStringSize(displayName, DISPLAYNAME_MAX);
457     if (err < 0) {
458         return err;
459     }
460     if (displayName.at(0) == '.') {
461         return -EINVAL;
462     }
463     static const string TITLE_REGEX_CHECK = R"([\\/:*?"'`<>|{}\[\]])";
464     if (RegexCheck(displayName, TITLE_REGEX_CHECK)) {
465         MEDIA_ERR_LOG("Failed to check displayName regex: %{private}s", displayName.c_str());
466         return -EINVAL;
467     }
468     return E_OK;
469 }
470 
471 int32_t MediaFileUtils::CheckRelativePath(const std::string &relativePath)
472 {
473     if (relativePath.empty()) {
474         return -EINVAL;
475     }
476 
477     int firstPoint = (relativePath.front() == '/') ? 1 : 0;
478     size_t lastPoint = 0;
479     while (true) {
480         lastPoint = relativePath.find_first_of('/', firstPoint);
481         if (lastPoint == string::npos) {
482             lastPoint = relativePath.length();
483         }
484         int len = lastPoint - firstPoint;
485         if (len == 0) {
486             MEDIA_ERR_LOG("relativePath %{public}s is invalid", relativePath.c_str());
487             return -EINVAL;
488         }
489         string checkedDirName = relativePath.substr(firstPoint, len);
490         if (CheckDentryName(checkedDirName) != E_OK) {
491             MEDIA_ERR_LOG("Dir Name %{public}s is invalid in path %{public}s",
492                 checkedDirName.c_str(), relativePath.c_str());
493             return -EINVAL;
494         }
495         if (lastPoint == relativePath.length()) {
496             break;
497         }
498         firstPoint = lastPoint + 1;
499         if (firstPoint == relativePath.length()) {
500             break;
501         }
502     }
503     return E_OK;
504 }
505 
506 void MediaFileUtils::FormatRelativePath(string &relativePath)
507 {
508     if (relativePath.empty()) {
509         return;
510     }
511     string FormatRelativePath = relativePath;
512     if (relativePath.back() != '/') {
513         relativePath += '/';
514     }
515     if (relativePath.front() == '/') {
516         relativePath = relativePath.substr(1);
517     }
518 }
519 
520 void MediaFileUtils::GetRootDirFromRelativePath(const string &relativePath, string &rootDir)
521 {
522     rootDir = relativePath;
523     if (relativePath.empty()) {
524         return;
525     }
526     if (relativePath.back() != '/') {
527         rootDir += '/';
528     }
529     if (rootDir[0] == '/') {
530         size_t dirIndex = rootDir.find_first_of('/', 1);
531         if (dirIndex == string::npos) {
532             return;
533         }
534         rootDir = rootDir.substr(1, dirIndex);
535     } else {
536         size_t dirIndex = rootDir.find_first_of('/');
537         if (dirIndex == string::npos) {
538             return;
539         }
540         rootDir = rootDir.substr(0, dirIndex + 1);
541     }
542 }
543 
544 int32_t MediaFileUtils::CheckAlbumName(const string &albumName)
545 {
546     int err = CheckStringSize(albumName, DISPLAYNAME_MAX);
547     if (err < 0) {
548         return err;
549     }
550 
551     static const string ALBUM_NAME_REGEX = R"([\.\\/:*?"'`<>|{}\[\]])";
552     if (RegexCheck(albumName, ALBUM_NAME_REGEX)) {
553         MEDIA_ERR_LOG("Failed to check album name regex: %{private}s", albumName.c_str());
554         return -EINVAL;
555     }
556     return E_OK;
557 }
558 
CheckDentryName(const string & dentryName)559 int32_t MediaFileUtils::CheckDentryName(const string &dentryName)
560 {
561     int err = CheckStringSize(dentryName, DISPLAYNAME_MAX);
562     if (err < 0) {
563         return err;
564     }
565 
566     static const string DENTRY_REGEX_CHECK = R"([\\/:*?"'`<>|{}\[\]])";
567     if (RegexCheck(dentryName, DENTRY_REGEX_CHECK)) {
568         MEDIA_ERR_LOG("Failed to check dentry regex: %{private}s", dentryName.c_str());
569         return -EINVAL;
570     }
571     return E_OK;
572 }
573 
574 string MediaFileUtils::GetLastDentry(const string &path)
575 {
576     string dentry = path;
577     size_t slashIndex = path.rfind('/');
578     if (slashIndex != string::npos) {
579         dentry = path.substr(slashIndex + 1);
580     }
581     return dentry;
582 }
583 
584 // @path should NOT start with OR end with '/'
585 string MediaFileUtils::GetFirstDentry(const string &path)
586 {
587     string dentry = path;
588     size_t slashIndex = path.find('/');
589     if (slashIndex != string::npos) {
590         dentry = path.substr(0, slashIndex);
591     }
592     return dentry;
593 }
594 
595 string MediaFileUtils::GetParentPath(const string &path)
596 {
597     string name;
598     size_t slashIndex = path.rfind("/");
599     if (slashIndex != string::npos) {
600         name = path.substr(0, slashIndex);
601     }
602 
603     return name;
604 }
605 
606 string MediaFileUtils::GetTitleFromDisplayName(const string &displayName)
607 {
608     string title;
609     if (!displayName.empty()) {
610         string::size_type pos = displayName.find_last_of('.');
611         if (pos == string::npos) {
612             return "";
613         }
614         title = displayName.substr(0, pos);
615     }
616     return title;
617 }
618 
619 int64_t MediaFileUtils::GetAlbumDateModified(const string &albumPath)
620 {
621     struct stat statInfo {};
622     if (!albumPath.empty() && stat(albumPath.c_str(), &statInfo) == 0) {
623         return (statInfo.st_mtime);
624     }
625     return 0;
626 }
627 
628 int64_t MediaFileUtils::UTCTimeSeconds()
629 {
630     struct timespec t{};
631     t.tv_sec = 0;
632     t.tv_nsec = 0;
633     clock_gettime(CLOCK_REALTIME, &t);
634     return (int64_t)(t.tv_sec);
635 }
636 
637 string MediaFileUtils::GetIdFromUri(const string &uri)
638 {
639     return MediaFileUri(uri).GetFileId();
640 }
641 
642 string MediaFileUtils::GetNetworkIdFromUri(const string &uri)
643 {
644     return MediaFileUri(uri).GetNetworkId();
645 }
646 
647 string MediaFileUtils::UpdatePath(const string &path, const string &uri)
648 {
649     MediaLibraryTracer tracer;
650     tracer.Start("MediaFileUtils::UpdatePath");
651 
652     string retStr = path;
653     MEDIA_INFO_LOG("MediaFileUtils::UpdatePath path = %{private}s, uri = %{private}s", path.c_str(), uri.c_str());
654     if (path.empty() || uri.empty()) {
655         return retStr;
656     }
657 
658     string networkId = GetNetworkIdFromUri(uri);
659     if (networkId.empty()) {
660         MEDIA_INFO_LOG("MediaFileUtils::UpdatePath retStr = %{private}s", retStr.c_str());
661         return retStr;
662     }
663 
664     size_t pos = path.find(MEDIA_DATA_DEVICE_PATH);
665     if (pos == string::npos) {
666         return retStr;
667     }
668 
669     string beginStr = path.substr(0, pos);
670     if (beginStr.empty()) {
671         return retStr;
672     }
673 
674     string endStr = path.substr(pos + MEDIA_DATA_DEVICE_PATH.length());
675     if (endStr.empty()) {
676         return retStr;
677     }
678 
679     retStr = beginStr + networkId + endStr;
680     MEDIA_INFO_LOG("MediaFileUtils::UpdatePath retStr = %{private}s", retStr.c_str());
681     return retStr;
682 }
683 
684 string MediaFileUtils::GetFileMediaTypeUri(int32_t mediaType, const string &networkId)
685 {
686     string uri = MEDIALIBRARY_DATA_ABILITY_PREFIX + networkId + MEDIALIBRARY_DATA_URI_IDENTIFIER;
687     switch (mediaType) {
688         case MEDIA_TYPE_AUDIO:
689             return uri + MEDIALIBRARY_TYPE_AUDIO_URI;
690         case MEDIA_TYPE_VIDEO:
691             return uri + MEDIALIBRARY_TYPE_VIDEO_URI;
692         case MEDIA_TYPE_IMAGE:
693             return uri + MEDIALIBRARY_TYPE_IMAGE_URI;
694         case MEDIA_TYPE_FILE:
695         default:
696             return uri + MEDIALIBRARY_TYPE_FILE_URI;
697     }
698 }
699 
700 string MediaFileUtils::GetFileMediaTypeUriV10(int32_t mediaType, const string &networkId)
701 {
702     string uri = MEDIALIBRARY_DATA_ABILITY_PREFIX + networkId + MEDIALIBRARY_DATA_URI_IDENTIFIER;
703     switch (mediaType) {
704         case MEDIA_TYPE_AUDIO:
705             return uri + AudioColumn::AUDIO_TYPE_URI;
706         case MEDIA_TYPE_VIDEO:
707         case MEDIA_TYPE_IMAGE:
708             return uri + PhotoColumn::PHOTO_TYPE_URI;
709         case MEDIA_TYPE_FILE:
710         default:
711             return uri + MEDIALIBRARY_TYPE_FILE_URI;
712     }
713 }
714 
715 string MediaFileUtils::GetUriByNameAndId(const string &displayName, const string &networkId, int32_t id)
716 {
717     MediaType mediaType = GetMediaType(displayName);
718 #ifdef MEDIALIBRARY_COMPATIBILITY
719     int64_t fileId = MediaFileUtils::GetVirtualIdByType(id, MediaType(mediaType));
720     return MediaFileUri(mediaType, to_string(fileId), networkId).ToString();
721 #else
722     return MediaFileUri(mediaType, to_string(id), networkId).ToString();
723 #endif
724 }
725 
726 MediaType MediaFileUtils::GetMediaType(const string &filePath)
727 {
728     if (filePath.empty()) {
729         return MEDIA_TYPE_ALL;
730     }
731 
732     string extention = GetExtensionFromPath(filePath);
733     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extention, MEDIA_MIME_TYPE_MAP);
734     return MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
735 }
736 
737 string MediaFileUtils::SplitByChar(const string &str, const char split)
738 {
739     size_t splitIndex = str.find_last_of(split);
740     return (splitIndex == string::npos) ? ("") : (str.substr(splitIndex + 1));
741 }
742 
743 string MediaFileUtils::GetExtensionFromPath(const string &path)
744 {
745     string extention = SplitByChar(path, '.');
746     if (!extention.empty()) {
747         transform(extention.begin(), extention.end(), extention.begin(), ::tolower);
748     }
749     return extention;
750 }
751 
752 int32_t MediaFileUtils::OpenFile(const string &filePath, const string &mode)
753 {
754     int32_t errCode = E_ERR;
755 
756     if (filePath.empty() || mode.empty()) {
757         MEDIA_ERR_LOG("Invalid open argument! mode: %{public}s, path: %{private}s", mode.c_str(), filePath.c_str());
758         return errCode;
759     }
760 
761     static const unordered_map<string, int32_t> MEDIA_OPEN_MODE_MAP = {
762         { MEDIA_FILEMODE_READONLY, O_RDONLY },
763         { MEDIA_FILEMODE_WRITEONLY, O_WRONLY },
764         { MEDIA_FILEMODE_READWRITE, O_RDWR },
765         { MEDIA_FILEMODE_WRITETRUNCATE, O_WRONLY | O_TRUNC },
766         { MEDIA_FILEMODE_WRITEAPPEND, O_WRONLY | O_APPEND },
767         { MEDIA_FILEMODE_READWRITETRUNCATE, O_RDWR | O_TRUNC },
768         { MEDIA_FILEMODE_READWRITEAPPEND, O_RDWR | O_APPEND },
769     };
770     if (MEDIA_OPEN_MODE_MAP.find(mode) == MEDIA_OPEN_MODE_MAP.end()) {
771         return E_ERR;
772     }
773 
774     if (filePath.size() >= PATH_MAX) {
775         MEDIA_ERR_LOG("File path too long %{public}d", (int)filePath.size());
776         return errCode;
777     }
778     string absFilePath;
779     if (!PathToRealPath(filePath, absFilePath)) {
780         MEDIA_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
781         return errCode;
782     }
783     if (absFilePath.empty()) {
784         MEDIA_ERR_LOG("Failed to obtain the canonical path for source path %{public}d %{private}s",
785                       errno, filePath.c_str());
786         return errCode;
787     }
788     MEDIA_INFO_LOG("File absFilePath is %{private}s", absFilePath.c_str());
789     return open(absFilePath.c_str(), MEDIA_OPEN_MODE_MAP.at(mode));
790 }
791 
792 int32_t MediaFileUtils::CreateAsset(const string &filePath)
793 {
794     MediaLibraryTracer tracer;
795     tracer.Start("MediaFileUtils::CreateAsset");
796 
797     int32_t errCode = E_ERR;
798 
799     if (filePath.empty()) {
800         MEDIA_ERR_LOG("Filepath is empty");
801         return E_VIOLATION_PARAMETERS;
802     }
803 
804     if (IsFileExists(filePath)) {
805         MEDIA_ERR_LOG("the file exists path: %{private}s", filePath.c_str());
806         return E_FILE_EXIST;
807     }
808 
809     size_t slashIndex = filePath.rfind('/');
810     if (slashIndex != string::npos) {
811         string fileName = filePath.substr(slashIndex + 1);
812         if (!fileName.empty() && fileName.at(0) != '.') {
813             size_t dotIndex = filePath.rfind('.');
814             if ((dotIndex == string::npos) && (GetMediaType(filePath) != MEDIA_TYPE_FILE)) {
815                 return errCode;
816             }
817         }
818     }
819 
820     ofstream file(filePath);
821     if (!file) {
822         MEDIA_ERR_LOG("Output file path could not be created errno %{public}d", errno);
823         return errCode;
824     }
825 
826     file.close();
827 
828     return E_SUCCESS;
829 }
830 
831 int32_t MediaFileUtils::ModifyAsset(const string &oldPath, const string &newPath)
832 {
833     int32_t err = E_MODIFY_DATA_FAIL;
834 
835     if (oldPath.empty() || newPath.empty()) {
836         MEDIA_ERR_LOG("Failed to modify asset, oldPath: %{private}s or newPath: %{private}s is empty!",
837             oldPath.c_str(), newPath.c_str());
838         return err;
839     }
840     if (!IsFileExists(oldPath)) {
841         MEDIA_ERR_LOG("Failed to modify asset, oldPath: %{private}s does not exist!", oldPath.c_str());
842         return E_NO_SUCH_FILE;
843     }
844     if (IsFileExists(newPath)) {
845         MEDIA_ERR_LOG("Failed to modify asset, newPath: %{private}s is already exist!", newPath.c_str());
846         return E_FILE_EXIST;
847     }
848     err = rename(oldPath.c_str(), newPath.c_str());
849     if (err < 0) {
850         MEDIA_ERR_LOG("Failed ModifyAsset errno %{public}d", errno);
851         return E_FILE_OPER_FAIL;
852     }
853 
854     return E_SUCCESS;
855 }
856 
857 int32_t MediaFileUtils::DeleteAsset(const string &filePath)
858 {
859     int32_t errCode = E_ERR;
860     if (!IsDirectory(filePath)) {
861         errCode = remove(filePath.c_str());
862     } else {
863         errCode = RemoveDirectory(filePath);
864     }
865     if (errCode != E_SUCCESS) {
866         MEDIA_ERR_LOG("DeleteAsset failed, filePath: %{private}s, errno: %{public}d, errmsg: %{public}s",
867             filePath.c_str(), errno, strerror(errno));
868     }
869     return errCode;
870 }
871 
872 int32_t MediaFileUtils::OpenAsset(const string &filePath, const string &mode)
873 {
874     if (filePath.empty()) {
875         return E_INVALID_PATH;
876     }
877     if (mode.empty()) {
878         return E_INVALID_MODE;
879     }
880 
881     int32_t flags = O_RDWR;
882     if (mode == MEDIA_FILEMODE_READONLY) {
883         flags = O_RDONLY;
884     } else if (mode == MEDIA_FILEMODE_WRITEONLY) {
885         flags = O_WRONLY;
886     } else if (mode == MEDIA_FILEMODE_WRITETRUNCATE) {
887         flags = O_WRONLY | O_TRUNC;
888     } else if (mode == MEDIA_FILEMODE_WRITEAPPEND) {
889         flags = O_WRONLY | O_APPEND;
890     } else if (mode == MEDIA_FILEMODE_READWRITETRUNCATE) {
891         flags = O_RDWR | O_TRUNC;
892     }
893 
894     if (filePath.size() >= PATH_MAX) {
895         MEDIA_ERR_LOG("File path too long %{public}d", (int)filePath.size());
896         return E_INVALID_PATH;
897     }
898     MEDIA_INFO_LOG("File path is %{private}s", filePath.c_str());
899     std::string absFilePath;
900     if (!PathToRealPath(filePath, absFilePath)) {
901         MEDIA_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
902         return E_INVALID_PATH;
903     }
904     if (absFilePath.empty()) {
905         MEDIA_ERR_LOG("Failed to obtain the canonical path for source path %{private}s %{public}d",
906                       filePath.c_str(), errno);
907         return E_INVALID_PATH;
908     }
909 
910     MEDIA_INFO_LOG("File absFilePath is %{private}s", absFilePath.c_str());
911     return open(absFilePath.c_str(), flags);
912 }
913 
914 int32_t MediaFileUtils::CloseAsset(int32_t fd)
915 {
916     return close(fd);
917 }
918 
919 std::string MediaFileUtils::GetMediaTypeUri(MediaType mediaType)
920 {
921     switch (mediaType) {
922         case MEDIA_TYPE_AUDIO:
923             return MEDIALIBRARY_AUDIO_URI;
924         case MEDIA_TYPE_VIDEO:
925             return MEDIALIBRARY_VIDEO_URI;
926         case MEDIA_TYPE_IMAGE:
927             return MEDIALIBRARY_IMAGE_URI;
928         case MEDIA_TYPE_SMARTALBUM:
929             return MEDIALIBRARY_SMARTALBUM_CHANGE_URI;
930         case MEDIA_TYPE_DEVICE:
931             return MEDIALIBRARY_DEVICE_URI;
932         case MEDIA_TYPE_FILE:
933         default:
934             return MEDIALIBRARY_FILE_URI;
935     }
936 }
937 
938 std::string MediaFileUtils::GetMediaTypeUriV10(MediaType mediaType)
939 {
940     switch (mediaType) {
941         case MEDIA_TYPE_AUDIO:
942             return AudioColumn::DEFAULT_AUDIO_URI;
943         case MEDIA_TYPE_VIDEO:
944         case MEDIA_TYPE_IMAGE:
945             return PhotoColumn::DEFAULT_PHOTO_URI;
946         case MEDIA_TYPE_SMARTALBUM:
947             return MEDIALIBRARY_SMARTALBUM_CHANGE_URI;
948         case MEDIA_TYPE_DEVICE:
949             return MEDIALIBRARY_DEVICE_URI;
950         case MEDIA_TYPE_FILE:
951         default:
952             return MEDIALIBRARY_FILE_URI;
953     }
954 }
955 
956 void MediaFileUtils::AppendFetchOptionSelection(std::string &selection, const std::string &newCondition)
957 {
958     if (!newCondition.empty()) {
959         if (!selection.empty()) {
960             selection = "(" + selection + ") AND " + newCondition;
961         } else {
962             selection = newCondition;
963         }
964     }
965 }
966 
967 bool MediaFileUtils::CheckMode(const string &mode)
968 {
969     if (mode.empty()) {
970         return false;
971     }
972     if (MEDIA_OPEN_MODES.find(mode) != MEDIA_OPEN_MODES.end()) {
973         return true;
974     } else {
975         MEDIA_ERR_LOG("Input Mode %{public}s is invalid", mode.c_str());
976         return false;
977     }
978 }
979 
980 size_t MediaFileUtils::FindIgnoreCase(const std::string &str, const std::string &key)
981 {
982     auto it = search(str.begin(), str.end(), key.begin(), key.end(), [](const char a, const char b) {
983         return ::tolower(a) == ::tolower(b);
984     });
985     if (it == str.end()) {
986         return string::npos;
987     }
988     size_t pos = it - str.begin();
989     return (pos > 0) ? pos : 0;
990 }
991 
992 int64_t MediaFileUtils::GetVirtualIdByType(int32_t id, MediaType type)
993 {
994     switch (type) {
995         case MediaType::MEDIA_TYPE_IMAGE:
996         case MediaType::MEDIA_TYPE_VIDEO: {
997             return (int64_t) id * VIRTUAL_ID_DIVIDER - PHOTO_VIRTUAL_IDENTIFIER;
998         }
999         case MediaType::MEDIA_TYPE_AUDIO: {
1000             return (int64_t) id * VIRTUAL_ID_DIVIDER - AUDIO_VIRTUAL_IDENTIFIER;
1001         }
1002         default: {
1003             return (int64_t)id * VIRTUAL_ID_DIVIDER - FILE_VIRTUAL_IDENTIFIER;
1004         }
1005     }
1006 }
1007 
1008 double MediaFileUtils::GetRealIdByTable(int32_t virtualId, const string &tableName)
1009 {
1010     if (tableName == PhotoColumn::PHOTOS_TABLE) {
1011         return (double) (virtualId + PHOTO_VIRTUAL_IDENTIFIER) / VIRTUAL_ID_DIVIDER;
1012     } else if (tableName == AudioColumn::AUDIOS_TABLE) {
1013         return (double) (virtualId + AUDIO_VIRTUAL_IDENTIFIER) / VIRTUAL_ID_DIVIDER;
1014     } else {
1015         return (double) (virtualId + FILE_VIRTUAL_IDENTIFIER) / VIRTUAL_ID_DIVIDER;
1016     }
1017 }
1018 
1019 string MediaFileUtils::GetVirtualUriFromRealUri(const string &uri, const string &extrUri)
1020 {
1021     if ((uri.find(PhotoColumn::PHOTO_TYPE_URI) != string::npos) ||
1022        (uri.find(AudioColumn::AUDIO_TYPE_URI) != string::npos)) {
1023         return uri;
1024     }
1025 
1026     string pureUri = uri;
1027     string suffixUri;
1028     size_t questionMaskPoint = uri.rfind('?');
1029     size_t hashKeyPoint = uri.rfind('#');
1030     if (questionMaskPoint != string::npos) {
1031         suffixUri = uri.substr(questionMaskPoint);
1032         pureUri = uri.substr(0, questionMaskPoint);
1033     } else if (hashKeyPoint != string::npos) {
1034         suffixUri = uri.substr(hashKeyPoint);
1035         pureUri = uri.substr(0, hashKeyPoint);
1036     }
1037 
1038     MediaFileUri fileUri(pureUri);
1039     string fileId = fileUri.GetFileId();
1040     if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
1041         return uri;
1042     }
1043 
1044     int32_t id = stoi(fileId);
1045     int64_t virtualId;
1046     MediaType type;
1047     if ((pureUri.find(MEDIALIBRARY_TYPE_IMAGE_URI) != string::npos)) {
1048         type = MediaType::MEDIA_TYPE_IMAGE;
1049         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_IMAGE);
1050     } else if (pureUri.find(MEDIALIBRARY_TYPE_VIDEO_URI) != string::npos) {
1051         type = MediaType::MEDIA_TYPE_VIDEO;
1052         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_VIDEO);
1053     } else if ((pureUri.find(MEDIALIBRARY_TYPE_AUDIO_URI) != string::npos)) {
1054         type = MediaType::MEDIA_TYPE_AUDIO;
1055         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_AUDIO);
1056     } else {
1057         type = MediaType::MEDIA_TYPE_FILE;
1058         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_FILE);
1059     }
1060     MediaFileUri virtualUri(type, to_string(virtualId), fileUri.GetNetworkId(),
1061         (fileUri.IsApi10() ? MEDIA_API_VERSION_V10 : MEDIA_API_VERSION_V9),
1062         (fileUri.IsApi10() ? extrUri : ""));
1063 
1064     if (suffixUri.empty()) {
1065         return virtualUri.ToString();
1066     } else {
1067         return virtualUri.ToString() + suffixUri;
1068     }
1069 }
1070 
1071 void GetExtrParamFromUri(const std::string &uri, std::string &displayName)
1072 {
1073     if (uri.find(PATH_PARA) != string::npos) {
1074         size_t lastSlashPosition = uri.rfind('/');
1075         if (lastSlashPosition != string::npos) {
1076             displayName = uri.substr(lastSlashPosition + 1);
1077         }
1078     }
1079 }
1080 
1081 string MediaFileUtils::GetRealUriFromVirtualUri(const string &uri)
1082 {
1083     if ((uri.find(PhotoColumn::PHOTO_TYPE_URI) != string::npos) ||
1084        (uri.find(AudioColumn::AUDIO_TYPE_URI) != string::npos)) {
1085         return uri;
1086     }
1087 
1088     string pureUri = uri;
1089     string suffixUri;
1090     size_t questionMaskPoint = uri.rfind('?');
1091     size_t hashKeyPoint = uri.rfind('#');
1092     if (questionMaskPoint != string::npos) {
1093         suffixUri = uri.substr(questionMaskPoint);
1094         pureUri = uri.substr(0, questionMaskPoint);
1095     } else if (hashKeyPoint != string::npos) {
1096         suffixUri = uri.substr(hashKeyPoint);
1097         pureUri = uri.substr(0, hashKeyPoint);
1098     }
1099 
1100     MediaFileUri fileUri(pureUri);
1101     string fileId = fileUri.GetFileId();
1102     if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
1103         return uri;
1104     }
1105     int32_t id = stoi(fileId);
1106     int32_t realId = 0;
1107     MediaType type;
1108     if ((pureUri.find(MEDIALIBRARY_TYPE_IMAGE_URI) != string::npos)) {
1109         type = MediaType::MEDIA_TYPE_IMAGE;
1110         realId = static_cast<int32_t>(GetRealIdByTable(id, PhotoColumn::PHOTOS_TABLE));
1111     } else if (pureUri.find(MEDIALIBRARY_TYPE_VIDEO_URI) != string::npos) {
1112         type = MediaType::MEDIA_TYPE_VIDEO;
1113         realId = static_cast<int32_t>(GetRealIdByTable(id, PhotoColumn::PHOTOS_TABLE));
1114     } else if ((pureUri.find(MEDIALIBRARY_TYPE_AUDIO_URI) != string::npos)) {
1115         type = MediaType::MEDIA_TYPE_AUDIO;
1116         realId = static_cast<int32_t>(GetRealIdByTable(id, AudioColumn::AUDIOS_TABLE));
1117     } else {
1118         type = MediaType::MEDIA_TYPE_FILE;
1119         realId = static_cast<int32_t>(GetRealIdByTable(id, MEDIALIBRARY_TABLE));
1120     }
1121     string extrUri;
1122     if (fileUri.IsApi10()) {
1123         string displayName;
1124         GetExtrParamFromUri(pureUri, displayName);
1125         extrUri = GetExtraUri(displayName, fileUri.GetFilePath());
1126     }
1127 
1128     MediaFileUri realUri(type, to_string(realId), fileUri.GetNetworkId(),
1129         (fileUri.IsApi10() ? MEDIA_API_VERSION_V10 : MEDIA_API_VERSION_V9), (fileUri.IsApi10() ? extrUri : ""));
1130 
1131     if (suffixUri.empty()) {
1132         return realUri.ToString();
1133     }
1134     return realUri.ToString() + suffixUri;
1135 }
1136 
1137 #ifdef MEDIALIBRARY_COMPATIBILITY
1138 string MediaFileUtils::GetTableFromVirtualUri(const std::string &virtualUri)
1139 {
1140     MediaFileUri uri(virtualUri);
1141     if (!uri.IsValid()) {
1142         MEDIA_ERR_LOG("virtual uri:%{private}s is invalid", virtualUri.c_str());
1143         return "";
1144     }
1145     string virtualId = uri.GetFileId();
1146     if (std::all_of(virtualId.begin(), virtualId.end(), ::isdigit)) {
1147         int64_t id = stol(virtualId);
1148         int64_t remainNumber = id % VIRTUAL_ID_DIVIDER;
1149         switch (remainNumber) {
1150             case VIRTUAL_ID_DIVIDER - PHOTO_VIRTUAL_IDENTIFIER:
1151                 return PhotoColumn::PHOTOS_TABLE;
1152             case VIRTUAL_ID_DIVIDER - AUDIO_VIRTUAL_IDENTIFIER:
1153                 return AudioColumn::AUDIOS_TABLE;
1154             case VIRTUAL_ID_DIVIDER - FILE_VIRTUAL_IDENTIFIER:
1155                 return MEDIALIBRARY_TABLE;
1156             default:
1157                 MEDIA_ERR_LOG("virtualId:%{public}ld is wrong", (long) id);
1158                 return "";
1159         }
1160     } else {
1161         MEDIA_ERR_LOG("virtual uri:%{private}s is invalid, can not get id", virtualUri.c_str());
1162         return "";
1163     }
1164 }
1165 #endif
1166 
1167 bool MediaFileUtils::IsUriV10(const string &mediaType)
1168 {
1169     return mediaType == URI_TYPE_PHOTO ||
1170         mediaType == URI_TYPE_PHOTO_ALBUM ||
1171         mediaType == URI_TYPE_AUDIO_V10;
1172 }
1173 
1174 bool MediaFileUtils::IsFileTablePath(const string &path)
1175 {
1176     if (path.empty() || path.size() <= ROOT_MEDIA_DIR.size()) {
1177         return false;
1178     }
1179 
1180     if (path.find(ROOT_MEDIA_DIR) == string::npos) {
1181         return false;
1182     }
1183 
1184     string relativePath = path.substr(ROOT_MEDIA_DIR.size());
1185     if ((relativePath.find(DOWNLOAD_DIR_VALUES) == 0) || (relativePath.find(DOC_DIR_VALUES) == 0)) {
1186         return true;
1187     }
1188     return false;
1189 }
1190 
1191 bool MediaFileUtils::IsPhotoTablePath(const string &path)
1192 {
1193     if (path.empty() || path.size() <= ROOT_MEDIA_DIR.size()) {
1194         return false;
1195     }
1196 
1197     if (path.find(ROOT_MEDIA_DIR) == string::npos) {
1198         return false;
1199     }
1200 
1201     string relativePath = path.substr(ROOT_MEDIA_DIR.size());
1202 
1203     const vector<string> photoPathVector = {
1204         PHOTO_BUCKET, PIC_DIR_VALUES, VIDEO_DIR_VALUES, CAMERA_DIR_VALUES
1205     };
1206     for (auto &photoPath : photoPathVector) {
1207         if (relativePath.find(photoPath) == 0) {
1208             return true;
1209         }
1210     }
1211     return false;
1212 }
1213 
1214 bool MediaFileUtils::StartsWith(const std::string &str, const std::string &prefix)
1215 {
1216     return str.compare(0, prefix.size(), prefix) == 0;
1217 }
1218 
1219 void MediaFileUtils::UriAppendKeyValue(string &uri, const string &key, std::string value)
1220 {
1221     string uriKey = key + '=';
1222     if (uri.find(uriKey) != string::npos) {
1223         return;
1224     }
1225 
1226     char queryMark = (uri.find('?') == string::npos) ? '?' : '&';
1227     string append = queryMark + key + '=' + value;
1228 
1229     size_t pos = uri.find('#');
1230     if (pos == string::npos) {
1231         uri += append;
1232     } else {
1233         uri.insert(pos, append);
1234     }
1235 }
1236 
1237 string MediaFileUtils::GetExtraUri(const string &displayName, const string &path)
1238 {
1239     string extraUri = "/" + GetTitleFromDisplayName(GetFileName(path)) + "/" + displayName;
1240     return MediaFileUtils::Encode(extraUri);
1241 }
1242 
1243 string MediaFileUtils::GetUriByExtrConditions(const string &prefix, const string &fileId, const string &suffix)
1244 {
1245     return prefix + fileId + suffix;
1246 }
1247 
1248 string MediaFileUtils::Encode(const string &uri)
1249 {
1250     const unordered_set<char> uriCompentsSet = {
1251         ';', ',', '/', '?', ':', '@', '&',
1252         '=', '+', '$', '-', '_', '.', '!',
1253         '~', '*', '(', ')', '\''
1254     };
1255     const int32_t encodeLen = 2;
1256     ostringstream outPutStream;
1257     outPutStream.fill('0');
1258     outPutStream << std::hex;
1259 
1260     for (unsigned char tmpChar : uri) {
1261         if (std::isalnum(tmpChar) || uriCompentsSet.find(tmpChar) != uriCompentsSet.end()) {
1262             outPutStream << tmpChar;
1263         } else {
1264             outPutStream << std::uppercase;
1265             outPutStream << '%' << std::setw(encodeLen) << static_cast<unsigned int>(tmpChar);
1266             outPutStream << std::nouppercase;
1267         }
1268     }
1269 
1270     return outPutStream.str();
1271 }
1272 
1273 } // namespace OHOS::Media
1274