Garbage Base64 decoded string [duplicate] - ruby

This question already has answers here:
p vs puts in Ruby
(8 answers)
Closed 3 years ago.
Could somebody explain me, why there are two various outputs?
CODE IN IRB(Interactive ruby shell):
irb(main):001:0> require 'base64'
=> true
irb(main):002:0> cookie = "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
=> "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
irb(main):003:0> decoded_cookie = Base64.urlsafe_decode64(URI.decode(cookie))
=> "asdfg--0D\x02 /\x8B\xDEM\x1A\a \x93U\xB4\xA7%\n\\Q(\xE8\x8B\x84\xBD\xDCa\x9A\xB7\xCB\xA8\xD5i\xB2#\xEF\xE4\x02 V\x7F0|\x85\x9F\xD3.5q\xBF\xB1\xF4\x8D\x1A\x87\xFE\x01 \x87\x91'\x9E'_j\x86s\x1C9\xEB\xB6"
Code from Linux terminal:
asd#asd:~# ruby script.rb
asdfg--0D /��M� �U��%
\Q(苄��a��˨�i�#�� V0|���.5q������ ��'�'_j�s9�
Script:
require 'base64'
require 'ecdsa'
cookie = "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
def decode_cookie(cookie)
decoded_cookie = Base64.urlsafe_decode64(URI.decode(cookie))
end
puts (decode_cookie(cookie))
How can i get the same output in terminal?
I need the output:
"asdfg--0D\x02 /\x8B\xDEM\x1A\a \x93U\xB4\xA7%\n\Q(\xE8\x8B\x84\xBD\xDCa\x9A\xB7\xCB\xA8\xD5i\xB2#\xEF\xE4\x02 V\x7F0|\x85\x9F\xD3.5q\xBF\xB1\xF4\x8D\x1A\x87\xFE\x01 \x87\x91'\x9E'_j\x86s\x1C9\xEB\xB6"
In Linux terminal.

A string like "\x8B" is a representation of character, not the literal \x8B. Ruby uses such representation if it's missing the font to display the character or if it messes with whitespacing (for example "\n" is a newline and not \ followed by a n).
The reason you get another output in irb is because you don't print the string using puts (like you do in your script). Simply calling decoded_cookie will return the string representation, not the actual content.
You can display the actual content by simply printing it to an output.
require 'base64'
cookie = "YXNkZmctLTBEAiAvi95NGgcgk1W0pyUKXFEo6IuEvdxhmrfLqNVpskDv5AIgVn8wfIWf0y41cb%2Bx9I0ah%2F4BIIeRJ54nX2qGcxw567Y%3D"
decoded_cookie = Base64.urlsafe_decode64(URI.decode(cookie))
puts decoded_cookie
# asdfg--0D /��M �U��%
# \Q(苄��a��˨�i�#�� V0|���.5q����� ��'�'_j�s9�
#=> nil
You can find more info about the "\xnn" representation here.
If you'd like the script to display the string representation use p instead of puts, or use puts decoded_cookie.inspect.

Related

Encode string as \uXXXX

I am trying to port a code from python to ruby, and having difficulties in one of the functions that encodes a UTF-8 string to JSON.
I have stripped down the code to what I believe is my problem.
I would like to make ruby output the exact same output as python.
The python code:
#!/usr/bin/env python
# encoding: utf-8
import json
import hashlib
text = "ÀÈG"
js = json.dumps( { 'data': text } )
print 'Python:'
print js
print hashlib.sha256(js).hexdigest()
The ruby code:
#!/usr/bin/env ruby
require 'json'
require 'digest'
text = "ÀÈG"
obj = {'data': text}
# js = obj.to_json # not using this, in order to get the space below
js = %Q[{"data": "#{text}"}]
puts 'Ruby:'
puts js
puts Digest::SHA256.hexdigest js
When I run both, this is the output:
$ ./test.rb && ./test.py
Ruby:
{"data": "ÀÈG"}
6cbe518180308038557d28ecbd53af66681afc59aacfbd23198397d22669170e
Python:
{"data": "\u00c0\u00c8G"}
a6366cbd6750dc25ceba65dce8fe01f283b52ad189f2b54ba1bfb39c7a0b96d3
What do I need to change in the ruby code to make its output identical to the python output (at least the final hash)?
Notes:
I have tried things from this SO question (and others) without success.
The code above produces identical results when using only english characters, so I know the hashing is the same.
Surely someone will come along with a more elegant (or at least a more efficient and robust) solution, but here's one for the time being:
#!/usr/bin/env ruby
require 'json'
require 'digest'
text = 'ÀÈG'
.encode('UTF-16') # convert UTF-8 characters to UTF-16
.inspect # escape UTF-16 characters and convert back to UTF-8
.sub(/^"\\u[Ff][Ee][Ff][Ff](.*?)"$/, '\1') # remove outer quotes and BOM
.gsub(/\\u\w{4}/, &:downcase!) # downcase alphas in escape sequences
js = { data: text } # wrap in containing data structure
.to_json(:space=>' ') # convert to JSON with spaces after colons
.gsub(/\\\\u(?=\w{4})/, '\\u') # remove extra backslashes
puts 'Ruby:', js, Digest::SHA256.hexdigest(js)
Output:
$ ./test.rb
Ruby:
{"data": "\u00c0\u00c8G"}
a6366cbd6750dc25ceba65dce8fe01f283b52ad189f2b54ba1bfb39c7a0b96d3

Print editable to console in Ruby [duplicate]

This question already has answers here:
What will give me something like ruby readline with a default value?
(6 answers)
Closed 6 years ago.
Let's say I have the following code in Ruby:
print("Enter a filename:")
editableprint("untitled.txt")
filename = gets.chomp!
What would be the function "editableprint" so that "untitled.txt" is part of the input of the user for the gets function? (thus the user can edit the "untitled.txt" string or simply leave it as is")
There are similar questions here and here
However, the solutions there don't seem to work as expected, so it looks this is ruby version or platform dependent?
For example, this does not work for me, but also does not throw an error.
require "readline"
filename = Readline.insert_text("untitled.txt").readline("Enter a filename:")
print filename
But since it looks much better, and should work according to the documentation for ruby >= 2, I am leaving it there for now.
The following works on my system (ruby 2.3.1, OS X)
require "readline"
require 'rb-readline'
module RbReadline
def self.prefill_prompt(str)
#rl_prefill = str
#rl_startup_hook = :rl_prefill_hook
end
def self.rl_prefill_hook
rl_insert_text #rl_prefill if #rl_prefill
#rl_startup_hook = nil
end
end
RbReadline.prefill_prompt("untitled.txt")
str = Readline.readline("Enter a filename:", true)
puts "You entered: #{str}"
I would use vim to edit the file. Vim will save edited files in ~/.viminfo. The last edited file is marked with '0. The pattern of a file entry is 'N N N filename where N stands for a integer.
def editableprint(filename)
system "vi #{filename}"
regex = /(?<='0\s{2}\d\s{2}\d\s{2}).*/
viminfo = File.expand_path("~/.viminfo")
File.read(viminfo).scan(regex).first
end
In order to make this to work you would have to change your code
print("Enter a filename:")
filename = gets.chomp!
filename = "untitled.txt" if filename.emtpy?
edited_filename = editableprint("untitled.txt")

Ruby: parse yaml from ANSI to UTF-8

Problem:
I have the yaml file test.yml that can be encoded in UTF-8 or ANSI:
:excel:
"Test":
"eins_Ä": :eins
"zwei_ä": :zwei
When I load the file I need it to be encoded in UTF-8 therefore tried to convert all of the Strings:
require 'yaml'
file = YAML::load_file('C:/Users/S61256/Desktop/test.yml')
require 'iconv'
CONV = Iconv.new("UTF-8", "ASCII")
class Test
def convert(hash)
hash.each{ |key, value|
convert(value) if value.is_a? Hash
CONV.iconv(value) if value.is_a? String
CONV.iconv(key) if key.is_a? String
}
end
end
t = Test.new
converted = t.convert(file)
p file
p converted
But when I try to run this example script it prints:
in 'iconv': eins_- (Iconv:IllegalSequence)
Questions:
1. Why does the error show up and how can I solve it?
2. Is there another (more appropiate) way to get the file's content in UTF-8?
Note:
I need this code to be compatible to Ruby 1.8 as well as Ruby 2.2. For Ruby 2.2 I would replace all the Iconv stuff with String::encode, but that's another topic.
The easiest way to deal with wrong encoded files is to read it in its original encoding, convert to UTF-8 and then pass to receiver (YAML in this case):
▶ YAML.load File.read('/tmp/q.yml', encoding: 'ISO-8859-1').force_encoding 'UTF-8'
#⇒ {:excel=>{"Test"=>{"eins_Ä"=>:eins, "zwei_ä"=>:zwei}}}
For Ruby 1.8 you should probably use Iconv, but the whole process (read as is, than encode, than yaml-load) remains the same.

What happens to the object I assign to $stdout in Ruby? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
EDIT: Don't bother reading this question, I just can't delete it. It's based on broken code and there's (almost) nothing to learn here.
I am redirecting console output in my Ruby program and although it works perfectly there is one thing I'm curious about:
Here's my code
capture = StringIO.new
$stdout = capture
puts "Hello World"
It looks like even though I'm assigning my capture object to $stdout, $stdout contains a new and different object after the assignment, but at least the type is correct.
In other words:
$stdout.to_s # => #<IO:0x2584b30>
capture = StringIO.new
$stdout = capture
$stdout.to_s # => #<StringIO:0x4fda948>
capture.to_s # => #<StringIO:0x4e3b220>
Subsequently $stdout.string contains "Hello World", but capture.string is empty.
Is there something happening behind the scenes or am I missing something here?
EDIT: This might be specific to certain versions only. I'm using Ruby 2.0.0-p247 on Windows 8.1
It works as expected.
>> capture = StringIO.new
=> #<StringIO:0x00000001ea8c00>
>> $stdout = capture
>> $stdout.to_s
>> capture.to_s
Above two line does not print anything because $stdout is now disconnected from terminal.
So I used $stderr.puts in following lines (can also use STDOUT.puts as Stefan commented):
>> $stderr.puts $stdout.to_s
#<StringIO:0x00000001ea8c00>
>> $stderr.puts capture.to_s
#<StringIO:0x00000001ea8c00>
$stdout.to_s, capture.to_s give me same result.
I used ruby 1.9.3. (Same for 2.0.0)
Are you sure there is no other manipulation of $stdout or capturehappening in between?
For me, output looks different. Both capture and $stdout are the same object and subsequently answer to string with the same response (ruby 1.9.2):
require 'stringio'
$stdout.to_s # => #<IO:0x2584b30>
capture = StringIO.new
$stdout = capture
puts $stdout.to_s # => #<StringIO:0x89a38c0>
puts capture.to_s # => #<StringIO:0x89a38c0>
puts "redirected"
$stderr.puts $stdout.string # => '#<StringIO:0x89a38c0>\n#<StringIO:0x89a38c0>\nredirected'
$stderr.puts capture.string # => '#<StringIO:0x89a38c0>\n#<StringIO:0x89a38c0>\nredirected'
Although this question was the result of overlooking a change to the value of $stdout, Ruby does have the ability to override assignment to global vars in this way, at least in the C api, using hooked variables.
$stdout actually does make use of this to check whether the new value is appropriate (it checks whether the new value responds to write) and raises an exception if it doesn’t.
If you really wanted (you don’t) you could create an extension that defines a global variable that automatically stores a different object than the value assigned, perhaps by called dup on it and using that instead:
#include "ruby.h"
VALUE foo;
static void foo_setter(VALUE val, ID id, VALUE *var){
VALUE dup_val = rb_funcall(val, rb_intern("dup"), 0);
*var = dup_val;
}
void Init_hooked() {
rb_define_hooked_variable("$foo", &foo, 0, foo_setter);
}
You could then use it like:
2.0.0-p247 :001 > require './ext/hooked'
=> true
2.0.0-p247 :002 > s = Object.new
=> #<Object:0x00000100b20560>
2.0.0-p247 :003 > $foo = s
=> #<Object:0x00000100b20560>
2.0.0-p247 :004 > s.to_s
=> "#<Object:0x00000100b20560>"
2.0.0-p247 :005 > $foo.to_s
=> "#<Object:0x00000100b3bea0>"
2.0.0-p247 :006 > s == $foo
=> false
Of course this is very similar to simply creating a setter method in a class that dups the vale and stores that, which you can do in plain Ruby:
def foo=(new_foo)
#foo = new_foo.dup
end
Since using global variables is generally bad design, it seems reasonable that this isn’t possible in Ruby for globals.

Thor & YAML outputting as binary?

I'm using Thor and trying to output YAML to a file. In irb I get what I expect. Plain text in YAML format. But when part of a method in Thor, its output is different...
class Foo < Thor
include Thor::Actions
desc "bar", "test"
def set
test = {"name" => "Xavier", "age" => 30}
puts test
# {"name"=>"Xavier", "age"=>30}
puts test.to_yaml
# !binary "bmFtZQ==": !binary |-
# WGF2aWVy
# !binary "YWdl": 30
File.open("data/config.yml", "w") {|f| f.write(test.to_yaml) }
end
end
Any ideas?
All Ruby 1.9 strings have an encoding attached to them.
YAML encodes some non-UTF8 strings as binary, even when they look innocent, without any high-bit characters. You might think that your code is always using UTF8, but builtins can return non-UTF8 strings (ex File path routines).
To avoid binary encoding, make sure all your strings encodings are UTF-8 before calling to_yaml. Change the encoding with force_encoding("UTF-8") method.
For example, this is how I encode my options hash into yaml:
options = {
:port => 26000,
:rackup => File.expand_path(File.join(File.dirname(__FILE__), "../sveg.rb"))
}
utf8_options = {}
options.each_pair { |k,v| utf8_options[k] = ((v.is_a? String) ? v.force_encoding("UTF-8") : v)}
puts utf8_options.to_yaml
Here is an example of yaml encoding simple strings as binary
>> x = "test"
=> "test"
>> x.encoding
=> #<Encoding:UTF-8>
>> x.to_yaml
=> "--- test\n...\n"
>> x.force_encoding "ASCII-8BIT"
=> "test"
>> x.to_yaml
=> "--- !binary |-\n dGVzdA==\n"
After version 1.9.3p125, ruby build-in YAML engine will treat all BINARY encoding differently than before. All you need to do is to set correct non-BINARY encoding before your String.to_yaml.
in Ruby 1.9, All String object have attached a Encoding object
and as following blog ( by James Edward Gray II ) mentioned, ruby have build in three type of encoding when String is generated:
http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings.
One of encoding may solve your problem => Source code Encoding
This is the encoding of your source code, and can be specify by adding magic encoding string at the first line or second line ( if you have a sha-bang string at the first line of your source code )
the magic encoding code could be one of following:
# encoding: utf-8
# coding: utf-8
# -- encoding : utf-8 --
so in your case, if you use ruby 1.9.3p125 or later, this should be solved by adding one of magic encoding in the beginning of your code.
# encoding: utf-8
require 'thor'
class Foo < Thor
include Thor::Actions
desc "bar", "test"
def bar
test = {"name" => "Xavier", "age" => 30}
puts test
#{"name"=>"Xavier", "age"=>30}
puts test["name"].encoding.name
#UTF-8
puts test.to_yaml
#---
#name: Xavier
#age: 30
puts test.to_yaml.encoding.name
#UTF-8
end
end
I have been struggling with this using 1.9.3p545 on Windows - just with a simple hash containing strings - and no Thor.
The gem ZAML solves the problem quite simply:
require 'ZAML'
yaml = ZAML.dump(some_hash)
File.write(path_to_yaml_file, yaml)

Resources