check if string is base64 - ruby-on-rails

i may recieve these two strings:
base = Base64.encode64(File.open("/home/usr/Desktop/test", "rb").read)
=> "YQo=\n"
string = File.open("/home/usr/Desktop/test", "rb").read
=> "a\n"
what i have tried so far is to check string with regular expression i-e. /([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==$)/ but this would be very heavy if the file is big.
I also have tried base.encoding.name and string.encoding.name but both returns the same.
I have also seen this post and got regular expression solution but any other solution ?
Any idea ? I just want to get is the string is actually text or base64 encoded text....

You can use something like this, not very performant but you are guaranteed not to get false positives:
require 'base64'
def base64?(value)
value.is_a?(String) && Base64.strict_encode64(Base64.decode64(value)) == value
end
The use of strict_encode64 versus encode64 prevents Ruby from inadvertently inserting newlines if you have a long string. See this post for details.

Related

Ruby on Rails: How to pluck hash from a string

I have a record of class String something like:
"{'1'=>'abc', '2'=> 'def'}"
but from this i need this in class Hash, something like:
{'1'=>'abc', '2'=> 'def'}
how to convert like this?
Edit: in my case i was getting this from CSV from other service where they were converting Hash into String before sending, so i asked them to send it using Base64.encode64 and now i am able to decode and get it in Hash format.
If you trust that the data is not nefarious you can write
str = "{'1'=>'abc', '2'=> 'def'}"
h = eval str
#=> {"1"=>"abc", "2"=>"def"}
See Kernel#eval.
If the data could be nefarious it would be safer to write
str.gsub(/{ *| *\|'/, '')
.split(/ *, */)
.map { |s| s.split(/ *=> */) }
.to_h
#=> {"1"=>"abc", "2"=>"def"}
This answer might not related to the question that i asked, but this is what solved my case, since other service was sending few Hash records in CSV format, they were converting the Hash to String before posting it to me.
So i asked them to use Base64.encode64 and send the encoded string in CSV.
Base64.encode64({'1'=>'abc', '2'=> 'def'}.to_json).delete("\n")
#=> "eyIxIjoiYWJjIiwiMiI6ImRlZiJ9"
and when i get the string i am converting it back to Hash something like
JSON.parse(Base64.decode64("eyIxIjoiYWJjIiwiMiI6ImRlZiJ9"))
#=> {"1"=>"abc", "2"=>"def"}
If I were writing a parser for objects that were in Ruby's object notation, not Javascript's, I'd call it either RON or RSON. I like the pun in the second better, so I think I'd go with RSON.
A quick google confirms that at least one other person thinks like I do, or at least arrives at the same conclusion: https://github.com/tannevaled/rson. So one option would be to use the rson gem, if it still works.
Alternatively, if you're not expecting any quotes or => to appear in any of the strings, you'd probably get away with something like
h = JSON.parse(str.gsub(/\s*=>\s*/, ":").gsub("'", '"'))

Unable to convert url params string to hash and then back to url string

Input is a params string (Input format cannot be changed)
something=1,2,3,4,5&something_else=6,7,8
Expected Output:
something=1,2,3,4,5&something_else=6,7,8
What I am doing:
params = 'something=1,2,3,4,5'
CGI::parse(params)
CGI.unescape(CGI.parse(params).to_query)
And I am getting this as output:
something[]=1,2,3,4,5
When I did CGI::parse(params)
I am getting this : {"something"=>["1,2,3,4,5"]}
which is wrong because it is not an array, something is a string which is "1,2,3,4,5" but it is being converted as array when I did CGI parse.
The reason I need to do CGI parse is because I need to manipulate the url PARAMS.
Is there any other possible way where I can convert it in the right way and maintain the params format?
The CGI module is a complete dinosaur and should probably be thrown in the garbage because of how bad it is, but for some reason it persists in the Ruby core. Maybe some day someone will refactor it and make it workable. Until then, skip it and use something better like URI, which is also built-in.
Given your irregular, non-compliant query string:
query_string = 'something=1,2,3,4,5&something_else=6,7,8'
You can handle this by using the decode_www_form method which handles query-strings:
require 'uri'
decoded = URI.decode_www_form(query_string).to_h
# => {"something"=>"1,2,3,4,5", "something_else"=>"6,7,8"}
To re-encode it you just call encode_www_form and then force unescape to undo what it's correctly doing to handle the , values:
encoded = URI.unescape(URI.encode_www_form(decoded))
# => "something=1,2,3,4,5&something_else=6,7,8"
That should get the effect you want.

How to check if string is SecureRandom.urlsafe_base64(64)

The string:
SecureRandom.urlsafe_base64(64)
#=> "nItIZhCvbne9zjU4JUWJOL46y53ERfmuQQW_FN4_ymk2EdbQr1NYOXTJVIeUWXhvRCe4OU3Is2ZEaHpiXXGYxw"
Random::Formatted.urlsafe_base64 implementation:
def urlsafe_base64(n=nil, padding=false)
s = [random_bytes(n)].pack("m0")
s.tr!("+/", "-_")
s.delete!("=") unless padding
s
end
So the question is basically what title says: is there a sane way to check whether string is generated with above method?
Maybe with some regexp? From docs:
The result may contain A-Z, a-z, 0-9, “-” and “_”. “=” is also used if
padding is true.
I would think there is not, because string is just a string, but I need to know if I can rely on anything more than its length while checking it.
Initial problem is that Rollbar gem filters API request Header with ***, and I'd like to change that so that I can see first n characterss of api token to track who made the failing request.
I'm gonna answer the literal question:
is there a sane way to check whether string is generated with above method?
Yes, there is. Kind of. Depends on where your boundaries of "sane" are. :)
Adapted from http://www.schneems.com/2016/01/25/ruby-debugging-magic-cheat-sheet.html
require 'objspace'
require 'securerandom'
ObjectSpace.trace_object_allocations_start
Kernel.send(:define_method, :sup) do |obj|
puts "#{ ObjectSpace.allocation_sourcefile(obj) }:#{ ObjectSpace.allocation_sourceline(obj) }"
end
str = SecureRandom.urlsafe_base64(64)
sup str
# >> /Users/sergio/.rubies/ruby-2.3.3/lib/ruby/2.3.0/securerandom.rb:169

trying to keep some escape characters.. but not others. ruby rails

I am having trouble formatting my string correctly. I am reading strings from a file and trying to use them as js code.
file_line = blah'blah"blah
string = line.gsub(/'/, "\\\'").gsub(/"/, "\\\"").dump
I want the output to be:
blah\'blah\"blah
But I cant seem to format it right. I have tried a bunch of things.
I'd use a single gsub matching both, ' and ", along with a block to prepend a \:
line = %q{blah'blah"blah}
string = line.gsub(/["']/) { |m| "\\#{m}" }
#=> "blah\\'blah\\\"blah"
puts string
Output:
blah\'blah\"blah
string = "blah'blah\"blah"
puts string.gsub(/'/,"\\\\'").gsub(/"/,'\"') # => blah\'blah\"blah
There's a whole lot of escaping going on here. To be honest I don't really understand the first one, but the second one is simple. I think in the first one we are escaping the backslash we want to add, and then escaping those two backslashes to avoid ruby interpretting them as a reference to the string. Or something. Trying to do a single level of escaping yields this:
puts string.gsub(/'/,"\\'").gsub(/"/,'\"') # => blahblah\"blahblah\"blah

Stripping the first character of a string

i have
string = "$575.00 "
string.to_f
// => 0.0
string = "575.00 "
string.to_f
// => 575.0
the value coming in is in this format and i need to insert into a database field that is decimal any suggestions
"$575.00 "
We did this so often we wrote an extension to String called cost_to_f:
class String
def cost_to_f
self.delete('$,').to_f
end
end
We store such extensions in config/initializers/extensions/string.rb.
You can then simply call:
"$5,425.55".cost_to_f #=> 5425.55
If you are using this method rarely, the best bet is to simply create a function, since adding functions to core classes is not exactly something I would recommend lightly:
def cost_to_f(string)
string.delete('$,').to_f
end
If you need it in more than one class, you can always put it in a module, then include that module wherever you need it.
One more tidbit. You mentioned that you need to process this string when it is being written to the database. With ActiveRecord, the best way to do this is:
class Item < ActiveRecord::Base
def price=(p)
p = p.cost_to_f if p.is_a?(String)
write_attribute(:price, p)
end
end
EDIT: Updated to use String#delete!
So many answers... i'll try to summarize all that are available now, before give own answer.
1. string.gsub(/[\$,]/, '')
string.gsub!(/^\$/, '')
2. string[1..-1]
3. string.slice(0) # => "ome string"
4. s/^.//
Why (g)sub and regexp Just for deleting a character? String#tr is faster and shorter. String#delete is even better.
Good, fast, simple. Power of reverse indexing.
Hm... looks like it returns "S". Because it is an alias to String#[]
Perl? /me is cheking question tags...
And my advice is:
What if you have not dollar, but yena? Or what if you don't even have anything before numbers?
So i'll prefer:
string[/\d.+/]
This will crop leading non-decimal symbols, that prevent to_f to work well.
P.S.: By the way. It's known, that float is bad practice for storing money amounts.
Use Float or Decimal for Accounting Application Dollar Amount?
You could try something like this.
string = string[1..-1] if string.match(/^\$/)
Or this.
string.gsub!(/^\$/, '')
Remember to put that backslash in your Regexp, it also means "end of string."
you can use regex for that:
s/^.//
As laways, this is PCRE syntax.
In Ruby, you can use the sub() method of the string class to replace the string:
result = string.sub(/^./,"")
This should work.
[EDIT]
Ok, someone asked what's the gsub() is for:
gsub() acts like sub() but with the /g modifier in PCRE (for global replacement):
s/a/b/
in PCRE is
string.sub(/a/, "b")
and
s/a/b/g
is
string.gsub(/a/, "b")
in Ruby
What I'd use (instead of regular expressions) is simply the built-in slice! method in the String class. For example,
s = "Some string"
s.slice!(0) # Deletes and returns the 0th character from the string.
s # => "ome string"
Documentation here.

Resources