Class: MrMurano::Webservice::File
- Inherits:
-
WebserviceBase
- Object
- WebserviceBase
- MrMurano::Webservice::File
- Defined in:
- lib/MrMurano/Webservice-File.rb
Overview
Static File content
Defined Under Namespace
Classes: FileItem
Constant Summary
Constants included from Verbose
Verbose::TABULARIZE_DATA_FORMAT_ERROR
Constants included from SolutionId
SolutionId::INVALID_API_ID, SolutionId::UNEXPECTED_TYPE_OR_ERROR_MSG
Constants included from AccountBase
AccountBase::LOGIN_ADVICE, AccountBase::LOGIN_NOTICE
Instance Attribute Summary
Attributes included from SolutionId
Class Method Summary collapse
Instance Method Summary collapse
- #curldebug(request) ⇒ Object
-
#docmp(item_a, item_b) ⇒ Object
Compare items.
- #dump_upload_curl(request, local) ⇒ Object
- #ensure_nonempty_upload(local) ⇒ Object
-
#fetch(path, _untainted = false, &block) ⇒ Object
Get one item of the static content.
-
#initialize ⇒ File
constructor
A new instance of File.
-
#list ⇒ Array<FileItem>
Get a list of all of the static content.
- #prepare_upload_form(local, remote) ⇒ Object
- #prepare_upload_req(remote) ⇒ Object
- #remote_item_checksum_md5(path) ⇒ Object
- #remote_item_checksum_sha1(path) ⇒ Object
-
#remove(path) ⇒ Object
Delete a file.
-
#synckey(item) ⇒ Object
The object to use a comparison key.
-
#to_remote_items(from, path) ⇒ Item
Hash of the details for the remote item for this path.
- #tolocalname(item, key) ⇒ Object
- #try_upload(local, remote) ⇒ Object
-
#upload(local, remote, _modify) ⇒ Object
Upload a file.
Methods inherited from WebserviceBase
Methods included from SyncUpDown
#config_vars_decode, #config_vars_encode, #debug_print_localitems, #diff_download, #diff_item_write, #download, #ignore?, #ignoring, #localitems, #locallist, #locallist_add_item, #locallist_complain_missing, #locallist_mark_seen, #location, #match, #remove_or_clear, #removelocal, #resolve_config_var_usage!, #resurrect_undeletables, #searchFor, #syncdown_after, #syncdown_before, #syncup_after, #syncup_before, #tolocalpath, #update_mtime
Methods included from Verbose
ask_yes_no, #ask_yes_no, #assert, assert, cmd_confirm_delete!, #cmd_confirm_delete!, debug, #debug, dump_file_json, dump_file_plain, dump_file_yaml, #dump_output_file, #error, error, #error_file_format!, fancy_ticks, #fancy_ticks, #load_file_json, #load_file_plain, #load_file_yaml, #load_input_file, outf, #outf, #outformat_engine, #pluralize?, pluralize?, #prepare_hash_csv, #read_hashf!, #tabularize, tabularize, verbose, #verbose, warning, #warning, #whirly_interject, whirly_interject, #whirly_linger, whirly_linger, #whirly_msg, whirly_msg, #whirly_pause, whirly_pause, #whirly_start, whirly_start, #whirly_stop, whirly_stop, #whirly_unpause, whirly_unpause
Methods included from SyncCore
#debug_selected, #dodiff, #dodiff_build_cmd, #dodiff_cull_tempfile_paths, #dodiff_do_diff, #dodiff_download_remote, #dodiff_flexible, #dodiff_header_aware, #dodiff_local_to_tempfile, #dodiff_prepare_local_and_diff, #dodiff_resolve_localname, #dodiff_tempfile_paths, #filter_solution, #init_mods_and_chgs_arrs, #item_dirty_set_status, #item_local_there_merged, #item_merged_diff_status, #item_merged_set_status, #item_select_selected!, #items_classify_and_find_duplicates, #items_cull_clashes!, #items_lists, #items_log_duplicates, #items_log_duplicates_there_local, #items_mods_and_chgs!, #items_new_and_old!, #select_selected!, #sort_by_name, #status, #sync_update_progress, #syncable_validate_api_id, #syncdown, #syncdown_item, #syncup, #syncup_item
Methods included from SyncAllowed
#download_item_allowed, #remove_item_allowed, #removelocal_item_allowed, #sync_item_allowed, #upload_item_allowed
Methods included from SolutionId
#affirm_valid, #api_id?, #endpoint, #init_api_id!, #valid_api_id?
Methods included from AccountBase
#add_headers, #ask_for_password!, #ask_for_user!, #cfg_clear_user_and_business, #credentials_reset, #get, #invalidate_token, #login_info, #logout, #must_prompt_if_logged_off!, #token, #token_reset, #verify_cfg_auth!, #verify_cfg_auth_persist, #verify_cfg_auth_scheme!, #verify_cfg_auth_ttl, #verify_set, warn_configfile_env_maybe
Methods included from Http
#add_headers, curldebug_after, curldebug_elapsed, curldebug_log, #delete, #endpoint, #get, #host, #http, #http_reset, #isJSON, #json_opts, #patch, #post, #postf, #put, #showHttpError, #user, #workit, #workit_response
Constructor Details
#initialize ⇒ File
Returns a new instance of File.
54 55 56 57 58 59 |
# File 'lib/MrMurano/Webservice-File.rb', line 54 def initialize super @uriparts << :file @itemkey = :path @project_section = :assets end |
Class Method Details
.description ⇒ Object
61 62 63 64 65 66 |
# File 'lib/MrMurano/Webservice-File.rb', line 61 def self.description # 2017-08-07: The UI calls these ASSETS in the tab # (and refers to "Static file hosting"). #%(Static File) %(Asset) end |
Instance Method Details
#curldebug(request) ⇒ Object
113 114 115 116 117 |
# File 'lib/MrMurano/Webservice-File.rb', line 113 def curldebug(request) # The upload will get printed out inside of upload. # Because we don't have the correct info here. super(request) if request.method != 'PUT' end |
#docmp(item_a, item_b) ⇒ Object
Compare items.
296 297 298 299 300 301 302 |
# File 'lib/MrMurano/Webservice-File.rb', line 296 def docmp(item_a, item_b) ( item_a[:mime_type] != item_b[:mime_type] || item_a[:checksum] != item_b[:checksum] || item_a[:size] != item_b[:size] ) end |
#dump_upload_curl(request, local) ⇒ Object
172 173 174 175 176 177 178 179 180 181 |
# File 'lib/MrMurano/Webservice-File.rb', line 172 def dump_upload_curl(request, local) a = [] a << %(curl -s -H 'Authorization: #{request['authorization']}') a << %(-H 'User-Agent: #{request['User-Agent']}') a << %(-X #{request.method}) a << %('#{request.uri}') a << %(-F file=@#{local}) ccmd = a.join(' ') MrMurano::Http.curldebug_log(ccmd, stamp_it: true) end |
#ensure_nonempty_upload(local) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/MrMurano/Webservice-File.rb', line 119 def ensure_nonempty_upload(local) # FIXME/MUR-6479/MUR-6477: (lb): Remove this function when backend fixed. # # {"statusCode":400, # "message":"The \"data\" argument must be one of type # string, TypedArray, or DataView", # "code":"BadRequestError" # } local = Pathname.new(local) unless local.is_a? Pathname if !local.size.zero? yield local else # Cannot use Tempfile.open because it make filename unique, e.g., # Tempfile.open(local.basename.to_s) { |tmpf| puts tmpf.path } # # /tmp/index.html20180413-15436-5i0s0u Dir.mktmpdir do |tmpdir| # NOTE: Because our class is named File, we have to descope ::File. ::File.open(::File.join(tmpdir, local.basename.to_s), 'w') do |tmpf| tmpf << "\n" tmpf.flush local = Pathname.new(tmpf.path) yield local end end end end |
#fetch(path, _untainted = false, &block) ⇒ Object
Get one item of the static content.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/MrMurano/Webservice-File.rb', line 82 def fetch(path, _untainted=false, &block) path = path[1..-1] if path[0] == '/' path = '/' + URI.encode_www_form_component(path) get(path) do |request, http| http.request(request) do |resp| case resp when Net::HTTPSuccess if block_given? resp.read_body(&block) else resp.read_body do |chunk| $stdout.write chunk end end else showHttpError(request, resp) end end nil end end |
#list ⇒ Array<FileItem>
Get a list of all of the static content
71 72 73 74 75 76 77 78 |
# File 'lib/MrMurano/Webservice-File.rb', line 71 def list ret = get return [] unless ret.is_a?(Array) ret.map { |i| FileItem.new(i) } # MAYBE/2017-08-17: # ret.map! { |i| FileItem.new(i) } # sort_by_name(ret) end |
#prepare_upload_form(local, remote) ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/MrMurano/Webservice-File.rb', line 157 def prepare_upload_form(local, remote) # http://stackoverflow.com/questions/184178/ # ruby-how-to-post-a-file-via-http-as-multipart-form-data # # Look at: https://github.com/httprb/http # If it works well, consider porting over to it. # # Or just: https://github.com/httprb/form_data.rb ? # # Most of these pull into ram. So maybe just go with that. Would guess that # truely large static content is rare, and we can optimize/fix that later. file = HTTP::FormData::File.new(local.to_s, content_type: remote[:mime_type]) HTTP::FormData.create(file: file) end |
#prepare_upload_req(remote) ⇒ Object
146 147 148 149 150 151 152 153 154 155 |
# File 'lib/MrMurano/Webservice-File.rb', line 146 def prepare_upload_req(remote) path = remote[:path] path = path[1..-1] if path[0] == '/' # JANKIE: The endpoint ends in /file, and this makes it /fileupload/, ha! uri = endpoint('upload/' + URI.encode_www_form_component(path)) # kludge past for a bit. #`curl -s -H 'Authorization: token #{@token}' '#{uri.to_s}' # -F file=@#{local.to_s}` Net::HTTP::Put.new(uri) end |
#remote_item_checksum_md5(path) ⇒ Object
283 284 285 |
# File 'lib/MrMurano/Webservice-File.rb', line 283 def remote_item_checksum_md5(path) Digest::MD5.file(path.to_s) end |
#remote_item_checksum_sha1(path) ⇒ Object
269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/MrMurano/Webservice-File.rb', line 269 def remote_item_checksum_sha1(path) # NOTE: It does not actually take the SHA1 of the file. It first # converts the file to hex, then takes the SHA1 of that string. xsum = Digest::SHA1.new path.open('rb:ASCII-8BIT') do |io| # rubocop:disable Lint/AssignmentInCondition # "Assignment in condition - you probably meant to use ==." while chunk = io.read(1_048_576) xsum << Digest.hexencode(chunk) end end xsum end |
#remove(path) ⇒ Object
Delete a file
107 108 109 110 111 |
# File 'lib/MrMurano/Webservice-File.rb', line 107 def remove(path) path = path[1..-1] if path[0] == '/' return unless remove_item_allowed(path) delete('/' + URI.encode_www_form_component(path)) end |
#synckey(item) ⇒ Object
Returns The object to use a comparison key.
289 290 291 |
# File 'lib/MrMurano/Webservice-File.rb', line 289 def synckey(item) item[:path] end |
#to_remote_items(from, path) ⇒ Item
Returns hash of the details for the remote item for this path.
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/MrMurano/Webservice-File.rb', line 230 def to_remote_items(from, path) items = super(from, path) name = items[0][:name] name = '/' if name == $cfg['files.default_page'] name = "/#{name}" unless name.chars.first == '/' mime = MIME::Types.type_for(path.to_s)[0] mime ||= MIME::Types['application/octet-stream'][0] file_size = path.size # FIXME/2018-04-13: (lb): When did platform switch from SHA1 to MD5? # Leaving this dead code block as a reminder to verify the new # behavior is the intended behavior. xsum_is_sha1 = false if xsum_is_sha1 digobj = remote_item_checksum_sha1(path) elsif file_size.zero? # MD5 of the empty string is not empty (it's d41d8cd98f00b204e9800998ecf8427e) # but BizAPI (or Pegasus; whomever) sends an empty string for an empty file. checksum = '' digobj = nil else digobj = remote_item_checksum_md5(path) end checksum = digobj.hexdigest unless digobj.nil? debug "Checking #{name} (#{mime.simplified} #{checksum})" item = FileItem.new( path: name, mime_type: mime.simplified, checksum: checksum, size: file_size, ) [item] end |
#tolocalname(item, key) ⇒ Object
220 221 222 223 224 225 |
# File 'lib/MrMurano/Webservice-File.rb', line 220 def tolocalname(item, key) name = item[key] # If service says '/', assume filename is e.g., 'index.html'. name = $cfg['files.default_page'] if name == '/' name end |
#try_upload(local, remote) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/MrMurano/Webservice-File.rb', line 201 def try_upload(local, remote) req = prepare_upload_req(remote) form = prepare_upload_form(local, remote) add_headers(req) return [nil, nil] unless upload_item_allowed(remote[@itemkey]) workit(req) do |request, http| request.content_type = form.content_type request.content_length = form.content_length request.body = form.to_s dump_upload_curl(request, local) if $cfg['tool.curldebug'] response = http.request(request) [request, response] end end |
#upload(local, remote, _modify) ⇒ Object
Upload a file
188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/MrMurano/Webservice-File.rb', line 188 def upload(local, remote, _modify) local = Pathname.new(local) unless local.is_a? Pathname request, response = try_upload(local, remote) return if response.nil? if response.is_a?(Net::HTTPBadRequest) && local.size.zero? ensure_nonempty_upload(local) do |nonempty_local| request, response = try_upload(nonempty_local, remote) end end return if response.is_a?(Net::HTTPSuccess) showHttpError(request, response) end |