From 06a89689d896268d4e997ae052cc52752c3b2d10 Mon Sep 17 00:00:00 2001 From: Emi Matchu Date: Fri, 27 Sep 2024 15:07:21 -0700 Subject: [PATCH] Oops, fix crash when modeling Patchwork Staff (AMFPHP string encoding!) See comment for details! I wonder if other items have been affected by this in the past. I think probably what happened before was that we successfully created this item, but failed to create the *translation*, so when migrating over the Patchwork Staff all its translated fields were empty? (That's what I found looking in the database today.) But yeah, thankfully our crash logging at health.openneo.net gave me the name of a pet someone was trying to model, and so I was able to find the bug and fix it! --- app/models/pet.rb | 4 +-- .../remote_gateway/request.rb | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/models/pet.rb b/app/models/pet.rb index a4aa5214..540a37a3 100644 --- a/app/models/pet.rb +++ b/app/models/pet.rb @@ -168,7 +168,7 @@ class Pet < ApplicationRecord # Return the response body as a `HashWithIndifferentAccess`. def self.send_amfphp_request(request, timeout: 10) begin - response = request.post(timeout: timeout, headers: { + response_data = request.post(timeout: timeout, headers: { "User-Agent" => Rails.configuration.user_agent_for_neopets, }) rescue RocketAMFExtensions::RemoteGateway::AMFError => e @@ -177,7 +177,7 @@ class Pet < ApplicationRecord raise DownloadError, e.message, e.backtrace end - HashWithIndifferentAccess.new(response.messages[0].data.body) + HashWithIndifferentAccess.new(response_data) end end diff --git a/lib/rocketamf_extensions/remote_gateway/request.rb b/lib/rocketamf_extensions/remote_gateway/request.rb index d102b6c3..9adde85a 100644 --- a/lib/rocketamf_extensions/remote_gateway/request.rb +++ b/lib/rocketamf_extensions/remote_gateway/request.rb @@ -54,7 +54,25 @@ module RocketAMFExtensions raise RocketAMF::AMFError.new(first_message_data) end - result + # HACK: It seems to me that these messages come back with Windows-1250 + # (or similar) encoding on the strings? I'm basing this on the + # Patchwork Staff item, whose description arrives as: + # + # "That staff is cute, but dont use it as a walking stick \x96 I " + + # "dont think it will hold you up!" + # + # And the `\x96` is meant to represent an endash, which it doesn't in + # UTF-8 or in most extended ASCII encodings, but *does* in Windows's + # specific extended ASCII. + # + # Idk if this is something to do with the AMFPHP spec or how the AMFPHP + # server code they use serializes strings (I couldn't find any + # reference to it?), or just their internal database encoding being + # passed along as-is, or what? But this seems to be the most correct + # interpretation I know how to do, so, let's do it! + result.messages[0].data.body.tap do |body| + reencode_strings! body, "Windows-1250", "UTF-8" + end end private @@ -86,6 +104,16 @@ module RocketAMFExtensions raise ConnectionError, e.message end end + + def reencode_strings!(target, from, to) + if target.is_a? String + target.force_encoding(from).encode!(to) + elsif target.is_a? Array + target.each { |x| reencode_strings!(x, from, to) } + elsif target.is_a? Hash + target.values.each { |x| reencode_strings!(x, from, to) } + end + end end class ConnectionError < RuntimeError