Skip to content

Commit

Permalink
add support for plain text filenameEnc (#946)
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreyNikiforov authored Sep 2, 2024
1 parent f93df7b commit d6ca702
Show file tree
Hide file tree
Showing 5 changed files with 11,880 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- fix: support plain text encoding for filename in addition to base64 [ref](https://github.com/boredazfcuk/docker-icloudpd/issues/641)

## 1.23.3 (2024-09-01)

- more debug added for parsing filenameEnc [#935](https://github.com/icloud-photos-downloader/icloud_photos_downloader/issues/935) and [ref](https://github.com/boredazfcuk/docker-icloudpd/issues/641)
Expand Down
33 changes: 28 additions & 5 deletions src/pyicloud_ipd/services/photos.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import re

from datetime import datetime
from typing import Any, Callable, Dict, Generator, Optional, Sequence, Tuple, TypeVar, Union
from typing import Any, Callable, Dict, Generator, Optional, Sequence, Tuple, TypeVar, Union, cast
import typing

from requests import Response
Expand All @@ -23,7 +23,7 @@
from pyicloud_ipd.file_match import FileMatchPolicy
from pyicloud_ipd.raw_policy import RawTreatmentPolicy
from pyicloud_ipd.session import PyiCloudSession
from pyicloud_ipd.utils import compose
from pyicloud_ipd.utils import compose, identity
from pyicloud_ipd.version_size import AssetVersionSize, LivePhotoVersionSize, VersionSize

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -614,15 +614,38 @@ def filename(self) -> str:
fields = self._master_record['fields']
if 'filenameEnc' in fields:
filename_enc: Dict[str, Any] = fields['filenameEnc']
def _get_value(input: Dict[str, Any]) -> Any:
return input['value']
def _get_value(input: Dict[str, Any]) -> str:
return cast(str,input['value'])
def _get_type(input: Dict[str, Any]) -> str:
return cast(str, input['type'])

def _match_type(string_parser: Callable[[str], str], base64_parser: Callable[[str], str]) -> Callable[[str], Callable[[str], str]]:
def _internal(type:str) -> Callable[[str], str]:
if type == "STRING":
return string_parser
elif type == "ENCRYPTED_BYTES":
return base64_parser
else:
raise ValueError(f"Unsupported filenam encoding {type}")
return _internal

parse_base64_value = compose(
bytes_decode('utf-8'),
base64.b64decode,
)

parser_selector = compose(
_match_type(identity, parse_base64_value),
_get_type
)

type_parser = wrap_param_in_exception("Parsing filenameEnc type", parser_selector)

_value_parser = type_parser(filename_enc)

parse_and_clean = compose(
self._service.filename_cleaner,
parse_base64_value
_value_parser
)

extract_value_and_parse = compose(
Expand Down
38 changes: 38 additions & 0 deletions tests/test_download_photos.py
Original file line number Diff line number Diff line change
Expand Up @@ -2165,3 +2165,41 @@ def test_download_bad_filename_utf8_encoding(self) -> None:

self.assertIsInstance(result.exception, ValueError)
# self.assertEqual(result.exception, ValueError("Invalid Input: b'i\\xb7\\x1dy\\xf8!'"))

def test_download_filename_string_encoding(self) -> None:
base_dir = os.path.join(self.fixtures_path, inspect.stack()[0][3])

files_to_create = [
("2018/07/30", "IMG_7408.JPG", 1151066),
("2018/07/30", "IMG_7407.JPG", 656257),
]

files_to_download: List[Tuple[str, str]] = [
# SU1HXzc0MDkuSlBH -> IMG_7409.JPG
("2018/07/31", "IMG_7409.JPG")
]

data_dir, result = run_icloudpd_test(
self.assertEqual,
self.vcr_path,
base_dir,
"listing_photos_filename_string_encoding.yml",
files_to_create,
files_to_download,
[
"--username",
"[email protected]",
"--password",
"password1",
"--recent",
"5",
"--skip-videos",
"--skip-live-photos",
"--no-progress-bar",
"--threads-num",
"1",
],
)
print_result_exception(result)

self.assertEqual(result.exit_code, 0)
38 changes: 38 additions & 0 deletions tests/test_download_photos_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -2153,3 +2153,41 @@ def test_download_bad_filename_utf8_encoding_name_id7(self) -> None:

self.assertIsInstance(result.exception, ValueError)
# self.assertEqual(result.exception, ValueError("Invalid Input: b'i\\xb7\\x1dy\\xf8!'"))

def test_download_filename_string_encoding_name_id7(self) -> None:
base_dir = os.path.join(self.fixtures_path, inspect.stack()[0][3])

files_to_create = [
("2018/07/30", "IMG_7408_QVI4T2l.JPG", 1151066),
("2018/07/30", "IMG_7407_QVovd0F.JPG", 656257),
]

files_to_download: List[Tuple[str, str]] = [
# SU1HXzc0MDkuSlBH -> IMG_7409.JPG
("2018/07/31", "IMG_7409_QVk2Yyt.JPG")
]

data_dir, result = run_icloudpd_test(
self.assertEqual,
self.vcr_path,
base_dir,
"listing_photos_filename_string_encoding.yml",
files_to_create,
files_to_download,
[
"--username",
"[email protected]",
"--password",
"password1",
"--recent",
"5",
"--skip-videos",
"--skip-live-photos",
"--no-progress-bar",
"--file-match-policy",
"name-id7",
],
)
print_result_exception(result)

self.assertEqual(result.exit_code, 0)
Loading

0 comments on commit d6ca702

Please sign in to comment.