2013-05-27 2 views
1

Я встречаю проблему с кодировкой ... Ошибок в консоли не возникает, но результат плохо кодируется. I должен использовать Digest::SHA1.hexdigest на строке, а затем долженpack результат.Ruby hexdigest sha1 pack ('H *') строковое кодирование ...

Приведенный ниже пример должен выводить '{'p) ODýGÎ- £ Iô8ü: iÀ', но он выводит '{? P) OD? GH? I? 8?: I?' в консоли и «{ p) OD G^BΗ I 8^D : i 'в файле журнала.

Итак, моя переменная под названием pack равна '{? P) OD? GH? I? 8?: I?' а не '{'p) ODýGÎ- £ Iô8ü: iÀ'. Это большая проблема ... Я делаю это в задаче Rails. Любые идеи?

Благодаря

# encoding: utf-8 
require 'digest/sha1' 

namespace :my_app do 
    namespace :check do 
     desc "Description" 

     task :weather => :environment do 

      hexdigest = Digest::SHA1.hexdigest('29d185d98c984a359e6e6f26a0474269partner=100043982026&code=34154&profile=large&filter=movie&striptags=synopsis%2Csynopsisshort&format=json&sed=20130527') 
      pack = [hexdigest].pack("H*") 

      puts pack # => {?p)OD?GΗ?I?8?:i? 
      puts '{´p)ODýGΗ£Iô8ü:iÀ' # => {´p)ODýGΗ£Iô8ü:iÀ 

     end 
    end 
end 
+1

Как вы знаете, выход должен быть «{'p) ODýGÎ- £ Iô8ü: iÀ '. В чем кодирование должно быть? –

+0

Я знаю это, потому что я сделал тот же скрипт в php, отображаемый в браузере. Вы можете взглянуть на 2-й аргумент http://bit.ly/bF6nNr . Приложение моего рельса находится в utf8 и моих локальных серверах. – Gozup

+0

Я не уверен, почему вы хотите, чтобы результат пакета являлся определенной * символьной * последовательностью? Обычно для байтовой строки, такой как дайджест, требуется соответствие определенной последовательности * байтов, а также необходимость ее отправки или сохранения с использованием четко определенной кодировки (шестнадцатеричный дайджест в ASCII - простая, но неэффективная схема).Если вы ожидаете определенную последовательность символов в качестве вывода и затем кодируете вывод вашего текущего веб-приложения, вам нужно будет указать кодировку, чтобы интерпретировать начальные байты байта как (я бы предположил, латинский-1), прежде чем вы конвертируете. –

ответ

0

Я думаю, что этот вопрос «кодирование» подвернулся за счет отладки другие части преобразования из PHP в Ruby. Целевой API, который будет потреблять дайджест параметров, выглядит так, как будто он примет переменную подписи, построенную в Ruby, следующим образом (edit: ну, это предположение, могут быть и существенные различия между Ruby и PHP в кодировке URI и по умолчанию base64):

require 'digest/sha1' 
require 'base64' 
require 'uri' 

sig_data = 'edhefhekjfhejk8edfefefefwjw69partne...' 
sig = URI.encode(Base64.encode64(Digest::SHA1.digest(sig_data))) 
=> "+ZabHg22Wyf7keVGNWTc4sK1ez4=%0A" 

Важное значение имеет точная конструкция sig_data по параметрам, которые подписываются. Это генерируется методом PHP http_build_query, и я не знаю, какой порядок или ускорение будет применяться к входным параметрам. Если ваша версия Ruby получит их в другом порядке или иначе пойдет на PHP, подпись будет неправильной (отредактируйте: на самом деле, возможно, мы ищем здесь подпись в точной строке запроса, отправленной API - я не знаю). Возможно, это проблема такого рода, которая привела вас к кроличьей дыре, как построена подпись?

+0

Ну, я позаботился о порядке параметров. Строка ввода точно такая же, как в PHP-версии ... Я вставил свой код ниже. – Gozup

+0

ОК, я не вижу, что отличается между Ruby и PHP, но это может быть просто из-за того, что я недостаточно знаю PHP. Я уверен, что ваша проблема - это * не * прямо кодировка символов из дайджеста или hexdigest/pack или хотя. –

+0

Спасибо, Нил, он работает сейчас. Ответ ниже. Но новая проблема. Если вы знаете, как его решить ... Еще раз спасибо – Gozup

0

Это то, что я сделал (мое преобразование из PHP в Ruby)

# encoding: utf-8 
require 'open-uri' 
require 'base64' 
require 'digest/sha1' 

class Allocine 

    $_api_url = 'http://api.allocine.fr/rest/v3' 
    $_partner_key 
    $_secret_key 
    $_user_agent = 'Dalvik/1.6.0 (Linux; U; Android 4.2.2; Nexus 4 Build/JDQ39E)' 

    def initialize (partner_key, secret_key) 
     $_partner_key = partner_key 
     $_secret_key = secret_key 
    end 

    def get(id) 
     # build the params 
     params = { 'partner' => $_partner_key, 
        'code' => id, 
        'profile' => 'large', 
        'filter' => 'movie', 
        'striptags' => 'synopsis,synopsisshort', 
        'format' => 'json' } 

     # do the request 
     response = _do_request('movie', params) 

     return response 
    end 

    private 
    def _do_request(method, params) 

     # build the URL 
     query_url = $_api_url + '/' + method 

     # new algo to build the query 
     http_build_query = Rack::Utils.build_query(params) 
     sed = DateTime.now.strftime('%Y%m%d') 
     sig = URI::encode(Base64.encode64(Digest::SHA1.digest($_secret_key + http_build_query + '&sed=' + sed))) 

     return sig 
    end 
end 

Затем вызовите

allocine = Allocine.new(ALLOCINE_PARTNER_KEY, ALLOCINE_SECRET_KEY) 
puts allocine.get('any ID') 

метод получить обратный 'e7RwKU9E% 2FUcCzpejSfQ4BPw6acA% 3D' в PHP и «cPf6I4ZP0qHQTSVgdKTbSspivzg =% 0A»в Руби ...

еще раз спасибо

0

спасибо, ребята, за вас r помощь. Проблема решена. С помощью следующего кода я получаю точно такой же строку с PHP:

http_build_query = Rack::Utils.build_query(params) 
sed = DateTime.now.strftime('%Y%m%d') 
sig = CGI::escape(Base64.strict_encode64(Digest::SHA1.digest($_secret_key + http_build_query + '&sed=' + sed))) 

Теперь я еще одна проблема, для которой я открыл new question here.

спасибо вам большое.