@@ -24,10 +24,20 @@ def initialize(primary_key, uuid, uti, note, backup, height, width, parent)
24
24
@parent = parent
25
25
@filename = get_media_filename
26
26
@filepath = get_media_filepath
27
- @backup = backup
27
+ @backup = backup
28
+ @zgeneration = get_zgeneration_for_thumbnail
28
29
29
30
# Find where on this computer that file is stored
31
+ back_up_file if ( @backup and @filepath . length > 0 and @filename . length > 0 )
32
+ end
33
+
34
+ ##
35
+ # This method handles setting the relevant +@backup_location+ variable
36
+ # and then backing up the file, if it exists.
37
+ def back_up_file
38
+ return if ( !@backup or !@filepath or @filepath . length == 0 )
30
39
@backup_location = @backup . get_real_file_path ( @filepath )
40
+ @logger . debug ( "Embedded Thumbnail #{ @uuid } : \n \t Expected Filepath: '#{ @filepath } ' (length: #{ @filepath . length } ), \n \t Expected location: '#{ @backup_location } ', \n \t Orphaned Parent: #{ @parent } " )
31
41
32
42
# Copy the file to our output directory if we can
33
43
@reference_location = @backup . back_up_file ( @filepath ,
@@ -42,6 +52,16 @@ def initialize(primary_key, uuid, uti, note, backup, height, width, parent)
42
52
@crypto_tag )
43
53
end
44
54
55
+ ##
56
+ # This method sets the thumbnail's Note object. It expects an AppleNote +note+
57
+ # and immediately calls AppleNotesEmbeddedObjects note= function before firing
58
+ # the thumbnail's get_zgeneration_for_thumbnail.
59
+ def note = ( note )
60
+ super ( note )
61
+ @zgeneration = get_zgeneration_for_thumbnail
62
+ back_up_file
63
+ end
64
+
45
65
##
46
66
# This method just returns a readable String for the object.
47
67
# Adds to the AppleNotesEmbeddedObject.to_s by pointing to where the media is.
@@ -53,37 +73,47 @@ def to_s
53
73
# This method returns the +filepath+ of this object.
54
74
# This is computed based on the assumed default storage location.
55
75
def get_media_filepath
56
- return get_media_filepath_ios16_and_earlier if @note . notestore . version < AppleNoteStore ::IOS_VERSION_17
76
+ return get_media_filepath_ios16_and_earlier if @version < AppleNoteStore ::IOS_VERSION_17
57
77
return get_media_filepath_ios17
58
78
end
59
79
60
80
##
61
81
# This method returns the +filepath+ of this object.
62
82
# This is computed based on the assumed default storage location.
83
+ # Examples of valid iOS 16 paths:
84
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-192x144-0.png
85
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-768x768-0.png.encrypted
86
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-216x384-0-oriented.png
87
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-144x192-0.jpg
88
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-288x384-0.jpg.encrypted
63
89
def get_media_filepath_ios16_and_earlier
64
- return "#{ @note . account . account_folder } Previews/#{ @uuid } . #{ get_thumbnail_extension } .encrypted " if @is_password_protected
65
- return "#{ @note . account . account_folder } Previews/#{ @uuid } . #{ get_thumbnail_extension } "
90
+ return "[Unknown Account]/ Previews/#{ @filename } " if ! @note
91
+ return "#{ @note . account . account_folder } Previews/#{ @filename } "
66
92
end
67
93
68
94
##
69
95
# This method returns the +filepath+ of this object.
70
96
# This is computed based on the assumed default storage location.
97
+ # Examples of valid iOS 17 paths:
98
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-272x384-0.png
99
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-768x768-0.png.encrypted
100
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-192x144-0/{zgeneration}/Preview.png
101
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-2384x3360-0/{zgeneration}/OrientedPreview.jpeg
71
102
def get_media_filepath_ios17
72
- zgeneration = get_zgeneration_for_thumbnail
73
- zgeneration = "#{ @uuid } /#{ zgeneration } /" if ( zgeneration and zgeneration . length > 0 )
103
+ zgeneration_string = ""
104
+ zgeneration_string = "#{ @uuid } /#{ @ zgeneration} /" if ( @ zgeneration and @ zgeneration. length > 0 )
74
105
75
- return "#{ @note . account . account_folder } Previews/#{ @uuid } .#{ get_thumbnail_extension } .encrypted" if @is_password_protected
76
- return "#{ @note . account . account_folder } Previews/#{ @uuid } .#{ get_thumbnail_extension } " if !zgeneration
77
- return "#{ @note . account . account_folder } Previews/#{ zgeneration } #{ @filename } "
106
+ return "[Unknown Account]/Previews/#{ @filename } " if !@note
107
+ return "#{ @note . account . account_folder } Previews/#{ zgeneration_string } #{ @filename } "
78
108
end
79
109
80
110
##
81
111
# As these are created by Notes, it is just the UUID. These are either
82
- # .png (apparently created by com.apple.notes.gallery) or .jpg (rest)
112
+ # .png (apparently created by com.apple.notes.gallery) or .jpeg/. jpg (rest)
83
113
# Encrypted thumbnails just have .encrypted added to the end.
84
114
def get_media_filename
85
- return get_media_filename_ios17 if @note . notestore . version >= AppleNoteStore ::IOS_VERSION_17
86
- return get_media_filename_ios16_and_earlier
115
+ return get_media_filename_ios16_and_earlier if @version < AppleNoteStore ::IOS_VERSION_17
116
+ return get_media_filename_ios17
87
117
end
88
118
89
119
##
@@ -96,20 +126,26 @@ def get_media_filename_ios16_and_earlier
96
126
end
97
127
98
128
##
99
- # As of iOS 17, these appear to be called Preview.png if there is a zgeneration.
129
+ # As of iOS 17, these appear to be called Preview.png if there is a zgeneration.
130
+ # Examples of valid paths:
131
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-768x768-0.png.encrypted
132
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-2384x3360-0/{zgeneration}/OrientedPreview.jpeg
133
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-192x144-0/{zgeneration}/Preview.png
134
+ # Accounts/{account_uuid}/Previews/{parent_uuid}-1-272x384-0.png
100
135
def get_media_filename_ios17
101
- zgeneration = get_zgeneration_for_thumbnail
136
+ # zgeneration = get_zgeneration_for_thumbnail
102
137
103
- return "#{ @uuid } .png.encrypted" if @is_password_protected
104
- return "Preview.#{ get_thumbnail_extension_ios17 } " if zgeneration
138
+ #return "#{@uuid}.png.encrypted" if @is_password_protected
139
+ return "#{ @uuid } .#{ get_thumbnail_extension_ios17 } .encrypted" if @is_password_protected
140
+ return "Preview.#{ get_thumbnail_extension_ios17 } " if @zgeneration
105
141
return "#{ @uuid } .#{ get_thumbnail_extension_ios17 } "
106
142
end
107
143
108
144
##
109
145
# This method fetches the appropriate ZFALLBACKGENERATION string to compute
110
146
# media location for iOS 17 and later.
111
147
def get_zgeneration_for_thumbnail
112
- return nil if @note . notestore . version < AppleNoteStore ::IOS_VERSION_17
148
+ return nil if @version < AppleNoteStore ::IOS_VERSION_17 or ! @database
113
149
@database . execute ( "SELECT ZICCLOUDSYNCINGOBJECT.ZGENERATION " +
114
150
"FROM ZICCLOUDSYNCINGOBJECT " +
115
151
"WHERE ZICCLOUDSYNCINGOBJECT.ZIDENTIFIER=?" ,
@@ -122,42 +158,48 @@ def get_zgeneration_for_thumbnail
122
158
# This method returns the thumbnail's extension. These are either
123
159
# .jpg (apparently created by com.apple.notes.gallery) or .png (rest).
124
160
def get_thumbnail_extension
125
- return get_thumbnail_extension_ios17 if @note . notestore . version >= AppleNoteStore ::IOS_VERSION_17
126
- return get_thumbnail_extension_ios16_and_earlier
161
+ return get_thumbnail_extension_ios16_and_earlier if @version < AppleNoteStore ::IOS_VERSION_17
162
+ return get_thumbnail_extension_ios17
127
163
end
128
164
129
165
##
130
166
# This method returns the thumbnail's extension. This is apparently png for iOS
131
- # 17 and later.
167
+ # 17 and later and jpeg for Galleries .
132
168
def get_thumbnail_extension_ios17
133
- return "jpeg" if ( @parent . type == "com.apple.notes.gallery" )
134
- return "jpeg" if ( @parent . parent and @parent . parent . type == "com.apple.notes.gallery" )
169
+ return "jpeg" if ( @parent and @parent . type == "com.apple.notes.gallery" )
170
+ return "jpeg" if ( @parent and @parent . parent and @parent . parent . type == "com.apple.notes.gallery" )
135
171
return "png"
136
172
end
137
173
138
174
##
139
175
# This method returns the thumbnail's extension. These are either
140
176
# .jpg (apparently created by com.apple.notes.gallery) or .png (rest) for iOS 16 and earlier.
141
177
def get_thumbnail_extension_ios16_and_earlier
142
- return "jpg" if ( @parent . type == "com.apple.notes.gallery" )
143
- return "jpg" if ( @parent . parent and @parent . parent . type == "com.apple.notes.gallery" )
178
+ return "jpg" if ( @parent and @parent . type == "com.apple.notes.gallery" )
179
+ return "jpg" if ( @parent and @parent . parent and @parent . parent . type == "com.apple.notes.gallery" )
144
180
return "png"
145
181
end
146
182
147
183
##
148
184
# This method generates the HTML necessary to display the image inline.
149
185
def generate_html ( individual_files )
150
- if ( @parent . reference_location and @reference_location )
186
+ if ( @parent and @reference_location )
187
+
188
+ # We default to the thumbnail's location to link to...
189
+ href_target = @reference_location
190
+ # ...but if possible, we use the parent's location to get the real file
191
+ href_target = @parent . reference_location if @parent . reference_location
192
+
151
193
root = @note . folder . to_relative_root ( individual_files )
152
194
builder = Nokogiri ::HTML ::Builder . new ( encoding : "utf-8" ) do |doc |
153
- doc . a ( href : "#{ root } #{ @parent . reference_location } " ) {
195
+ doc . a ( href : "#{ root } #{ href_target } " ) {
154
196
doc . img ( src : "#{ root } #{ @reference_location } " )
155
197
} . attr ( "data-apple-notes-zidentifier" => "#{ @parent . uuid } " )
156
198
end
157
199
return builder . doc . root
158
200
end
159
201
160
- return "{Image missing due to not having file reference point}"
202
+ return "{Thumbnail missing due to not having file reference point}"
161
203
end
162
204
163
205
##
0 commit comments