opentok 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +11 -0
- data/LICENCE +19 -0
- data/README.textile +43 -0
- data/doc/CHANGES.html +128 -0
- data/doc/Gemfile.html +114 -0
- data/doc/Hash.html +228 -0
- data/doc/LICENCE.html +133 -0
- data/doc/Net.html +167 -0
- data/doc/Net/HTTP.html +260 -0
- data/doc/OpenTok.html +173 -0
- data/doc/OpenTok/OpenTokException.html +172 -0
- data/doc/OpenTok/OpenTokSDK.html +520 -0
- data/doc/OpenTok/RoleConstants.html +190 -0
- data/doc/OpenTok/Session.html +284 -0
- data/doc/OpenTok/SessionPropertyConstants.html +195 -0
- data/doc/Rakefile.html +111 -0
- data/doc/created.rid +13 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +100 -0
- data/doc/js/darkfish.js +116 -0
- data/doc/js/jquery.js +32 -0
- data/doc/js/quicksearch.js +114 -0
- data/doc/js/thickbox-compressed.js +10 -0
- data/doc/lib/monkey_patches_rb.html +52 -0
- data/doc/lib/open_tok/exceptions_rb.html +52 -0
- data/doc/lib/open_tok/open_tok_sdk_rb.html +64 -0
- data/doc/lib/open_tok/session_rb.html +52 -0
- data/doc/lib/open_tok/version_rb.html +52 -0
- data/doc/lib/opentok_rb.html +70 -0
- data/doc/rdoc.css +706 -0
- data/doc/spec/opentok_spec_rb.html +54 -0
- data/doc/spec/spec_helper_rb.html +54 -0
- data/lib/monkey_patches.rb +34 -0
- data/lib/open_tok/exceptions.rb +16 -0
- data/lib/open_tok/open_tok_sdk.rb +147 -0
- data/lib/open_tok/session.rb +25 -0
- data/lib/open_tok/version.rb +3 -0
- data/lib/opentok.rb +7 -14
- data/opentok.gemspec +2 -2
- data/spec/opentok_spec.rb +64 -0
- data/spec/spec_helper.rb +2 -0
- metadata +68 -12
- data/lib/opentok/version.rb +0 -3
@@ -0,0 +1,54 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
4
|
+
|
5
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
6
|
+
<head>
|
7
|
+
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
8
|
+
|
9
|
+
<title>File: opentok_spec.rb [RDoc Documentation]</title>
|
10
|
+
|
11
|
+
<link type="text/css" media="screen" href="../rdoc.css" rel="stylesheet" />
|
12
|
+
|
13
|
+
<script src="../js/jquery.js" type="text/javascript"
|
14
|
+
charset="utf-8"></script>
|
15
|
+
<script src="../js/thickbox-compressed.js" type="text/javascript"
|
16
|
+
charset="utf-8"></script>
|
17
|
+
<script src="../js/quicksearch.js" type="text/javascript"
|
18
|
+
charset="utf-8"></script>
|
19
|
+
<script src="../js/darkfish.js" type="text/javascript"
|
20
|
+
charset="utf-8"></script>
|
21
|
+
</head>
|
22
|
+
|
23
|
+
<body class="file file-popup">
|
24
|
+
<div id="metadata">
|
25
|
+
<dl>
|
26
|
+
<dt class="modified-date">Last Modified</dt>
|
27
|
+
<dd class="modified-date">Mon Apr 11 13:42:22 +0200 2011</dd>
|
28
|
+
|
29
|
+
|
30
|
+
<dt class="requires">Requires</dt>
|
31
|
+
<dd class="requires">
|
32
|
+
<ul>
|
33
|
+
|
34
|
+
<li>spec_helper</li>
|
35
|
+
|
36
|
+
</ul>
|
37
|
+
</dd>
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
</dl>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div id="documentation">
|
45
|
+
|
46
|
+
<div class="description">
|
47
|
+
<h2>Description</h2>
|
48
|
+
|
49
|
+
</div>
|
50
|
+
|
51
|
+
</div>
|
52
|
+
</body>
|
53
|
+
</html>
|
54
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
4
|
+
|
5
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
6
|
+
<head>
|
7
|
+
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
8
|
+
|
9
|
+
<title>File: spec_helper.rb [RDoc Documentation]</title>
|
10
|
+
|
11
|
+
<link type="text/css" media="screen" href="../rdoc.css" rel="stylesheet" />
|
12
|
+
|
13
|
+
<script src="../js/jquery.js" type="text/javascript"
|
14
|
+
charset="utf-8"></script>
|
15
|
+
<script src="../js/thickbox-compressed.js" type="text/javascript"
|
16
|
+
charset="utf-8"></script>
|
17
|
+
<script src="../js/quicksearch.js" type="text/javascript"
|
18
|
+
charset="utf-8"></script>
|
19
|
+
<script src="../js/darkfish.js" type="text/javascript"
|
20
|
+
charset="utf-8"></script>
|
21
|
+
</head>
|
22
|
+
|
23
|
+
<body class="file file-popup">
|
24
|
+
<div id="metadata">
|
25
|
+
<dl>
|
26
|
+
<dt class="modified-date">Last Modified</dt>
|
27
|
+
<dd class="modified-date">Mon Apr 11 11:20:45 +0200 2011</dd>
|
28
|
+
|
29
|
+
|
30
|
+
<dt class="requires">Requires</dt>
|
31
|
+
<dd class="requires">
|
32
|
+
<ul>
|
33
|
+
|
34
|
+
<li>I18n</li>
|
35
|
+
|
36
|
+
</ul>
|
37
|
+
</dd>
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
</dl>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div id="documentation">
|
45
|
+
|
46
|
+
<div class="description">
|
47
|
+
<h2>Description</h2>
|
48
|
+
|
49
|
+
</div>
|
50
|
+
|
51
|
+
</div>
|
52
|
+
</body>
|
53
|
+
</html>
|
54
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
=begin
|
2
|
+
OpenTok Ruby Library
|
3
|
+
http://www.tokbox.com/
|
4
|
+
|
5
|
+
Copyright 2010, TokBox, Inc.
|
6
|
+
|
7
|
+
Last modified: 2011-02-17
|
8
|
+
=end
|
9
|
+
|
10
|
+
class Hash
|
11
|
+
|
12
|
+
# Adding a urlencode method to the hash class for easy querstring generation
|
13
|
+
def urlencode
|
14
|
+
to_a.map do |name_value|
|
15
|
+
if name_value[1].is_a? Array
|
16
|
+
name_value[0] = CGI.escape name_value[0].to_s
|
17
|
+
name_value[1].map { |e| CGI.escape e.to_s }
|
18
|
+
name_value[1] = name_value[1].join "&" + name_value[0] + "="
|
19
|
+
name_value.join '='
|
20
|
+
else
|
21
|
+
name_value.map { |e| CGI.escape e.to_s }.join '='
|
22
|
+
end
|
23
|
+
end.join '&'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Net::HTTP
|
28
|
+
alias_method :old_initialize, :initialize
|
29
|
+
def initialize(*args)
|
30
|
+
old_initialize(*args)
|
31
|
+
@ssl_context = OpenSSL::SSL::SSLContext.new
|
32
|
+
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
=begin
|
2
|
+
OpenTok Ruby Library
|
3
|
+
http://www.tokbox.com/
|
4
|
+
|
5
|
+
Copyright 2010, TokBox, Inc.
|
6
|
+
|
7
|
+
=end
|
8
|
+
|
9
|
+
module OpenTok
|
10
|
+
|
11
|
+
# The exception that gets thrown when an invalid api-key and/or secret is given.
|
12
|
+
class OpenTokException < RuntimeError
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,147 @@
|
|
1
|
+
=begin
|
2
|
+
OpenTok Ruby Library
|
3
|
+
http://www.tokbox.com/
|
4
|
+
|
5
|
+
Copyright 2010, TokBox, Inc.
|
6
|
+
|
7
|
+
=end
|
8
|
+
|
9
|
+
require 'cgi'
|
10
|
+
require 'openssl'
|
11
|
+
require 'base64'
|
12
|
+
require 'uri'
|
13
|
+
require 'net/https'
|
14
|
+
require 'rexml/document'
|
15
|
+
|
16
|
+
DIGEST = OpenSSL::Digest::Digest.new('sha1')
|
17
|
+
|
18
|
+
module OpenTok
|
19
|
+
|
20
|
+
class SessionPropertyConstants
|
21
|
+
ECHOSUPPRESSION_ENABLED = "echoSuppression.enabled"; #Boolean
|
22
|
+
MULTIPLEXER_NUMOUTPUTSTREAMS = "multiplexer.numOutputStreams"; #Integer
|
23
|
+
MULTIPLEXER_SWITCHTYPE = "multiplexer.switchType"; #Integer
|
24
|
+
MULTIPLEXER_SWITCHTIMEOUT = "multiplexer.switchTimeout"; #Integer
|
25
|
+
end
|
26
|
+
|
27
|
+
class RoleConstants
|
28
|
+
SUBSCRIBER = "subscriber" #Can only subscribe
|
29
|
+
PUBLISHER = "publisher" #Can publish, subscribe, and signal
|
30
|
+
MODERATOR = "moderator" #Can do the above along with forceDisconnect and forceUnpublish
|
31
|
+
end
|
32
|
+
|
33
|
+
class OpenTokSDK
|
34
|
+
attr_accessor :api_url
|
35
|
+
|
36
|
+
@@TOKEN_SENTINEL = "T1=="
|
37
|
+
@@SDK_VERSION = "tbruby-%s" % [ VERSION ]
|
38
|
+
|
39
|
+
# Create a new OpenTokSDK object.
|
40
|
+
#
|
41
|
+
# The first two attributes are required; +parnter_id+ and +partner_secret+ are the api-key and secret
|
42
|
+
# that are provided to you.
|
43
|
+
#
|
44
|
+
# You can also pass in optional options;
|
45
|
+
# * +:api_url+ sets the location of the api (staging or production)
|
46
|
+
def initialize(partner_id, partner_secret, options = nil)
|
47
|
+
@partner_id = partner_id
|
48
|
+
@partner_secret = partner_secret.strip
|
49
|
+
|
50
|
+
if options.is_a?(::Hash)
|
51
|
+
@api_url = options[:api_url] || API_URL
|
52
|
+
end
|
53
|
+
|
54
|
+
unless @api_url
|
55
|
+
@api_url = API_URL
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Generate token for the given session_id. The options you can provide are;
|
60
|
+
# * +:session_id+ (required) generate a token for the provided session
|
61
|
+
# * +:create_time+
|
62
|
+
# * +:expire_time+ (optional) The time when the token will expire, defined as an integer value for a Unix timestamp (in seconds). If you do not specify this value, tokens expire in 24 hours after being created.
|
63
|
+
# * +:role+ (optional) Added in OpenTok v0.91.5. This defines the role the user will have. There are three roles: subscriber, publisher, and moderator.
|
64
|
+
#
|
65
|
+
# See http://www.tokbox.com/opentok/tools/documentation/overview/token_creation.html for more information on all options.
|
66
|
+
def generate_token(opts = {})
|
67
|
+
{:session_id=>nil, :create_time=>nil, :expire_time=>nil, :role=>nil}.merge!(opts)
|
68
|
+
|
69
|
+
create_time = opts[:create_time].nil? ? Time.now : opts[:create_time]
|
70
|
+
session_id = opts[:session_id].nil? ? '' : opts[:session_id]
|
71
|
+
role = opts[:role].nil? ? RoleConstants::PUBLISHER : opts[:role]
|
72
|
+
|
73
|
+
data_params = {
|
74
|
+
:role => role,
|
75
|
+
:session_id => session_id,
|
76
|
+
:create_time => create_time.to_i,
|
77
|
+
:nonce => rand
|
78
|
+
}
|
79
|
+
|
80
|
+
if not opts[:expire_time].nil?
|
81
|
+
data_params[:expire_time] = opts[:expire_time].to_i
|
82
|
+
end
|
83
|
+
|
84
|
+
data_string = data_params.urlencode
|
85
|
+
|
86
|
+
sig = sign_string(data_string, @partner_secret)
|
87
|
+
meta_string = {
|
88
|
+
:partner_id => @partner_id,
|
89
|
+
:sdk_version => @@SDK_VERSION,
|
90
|
+
:sig => sig
|
91
|
+
}.urlencode
|
92
|
+
|
93
|
+
@@TOKEN_SENTINEL + Base64.encode64(meta_string + ":" + data_string).gsub("\n","")
|
94
|
+
end
|
95
|
+
|
96
|
+
# Generates a new OpenTok::Session and set it's session_id, situating it in TokBox's global network near the IP of the specified @location@.
|
97
|
+
#
|
98
|
+
# See http://www.tokbox.com/opentok/tools/documentation/overview/session_creation.html for more information
|
99
|
+
def create_session(location='', opts={})
|
100
|
+
opts.merge!({:partner_id => @partner_id, :location=>location})
|
101
|
+
doc = do_request("/session/create", opts)
|
102
|
+
if not doc.get_elements('Errors').empty?
|
103
|
+
raise OpenTokException.new doc.get_elements('Errors')[0].get_elements('error')[0].children.to_s
|
104
|
+
end
|
105
|
+
OpenTok::Session.new(doc.root.get_elements('Session')[0].get_elements('session_id')[0].children[0].to_s)
|
106
|
+
end
|
107
|
+
|
108
|
+
protected
|
109
|
+
def sign_string(data, secret)
|
110
|
+
OpenSSL::HMAC.hexdigest(DIGEST, secret, data)
|
111
|
+
end
|
112
|
+
|
113
|
+
def do_request(api_url, params, token=nil)
|
114
|
+
url = URI.parse(@api_url + api_url)
|
115
|
+
if not params.empty?
|
116
|
+
req = Net::HTTP::Post.new(url.path)
|
117
|
+
req.set_form_data(params)
|
118
|
+
else
|
119
|
+
req = Net::HTTP::Get.new(url.path)
|
120
|
+
end
|
121
|
+
|
122
|
+
if not token.nil?
|
123
|
+
req.add_field 'X-TB-TOKEN-AUTH', token
|
124
|
+
else
|
125
|
+
req.add_field 'X-TB-PARTNER-AUTH', "#{@partner_id}:#{@partner_secret}"
|
126
|
+
end
|
127
|
+
http = Net::HTTP.new(url.host, url.port)
|
128
|
+
http.use_ssl = true if @api_url.start_with?("https")
|
129
|
+
res = http.start {|http| http.request(req)}
|
130
|
+
case res
|
131
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
132
|
+
# OK
|
133
|
+
doc = REXML::Document.new(res.read_body)
|
134
|
+
return doc
|
135
|
+
else
|
136
|
+
res.error!
|
137
|
+
end
|
138
|
+
rescue Net::HTTPExceptions
|
139
|
+
raise
|
140
|
+
raise OpenTokException.new 'Unable to create fufill request: ' + $!
|
141
|
+
rescue NoMethodError
|
142
|
+
raise
|
143
|
+
raise OpenTokException.new 'Unable to create a fufill request at this time: ' + $1
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
=begin
|
2
|
+
OpenTok Ruby Library v0.90.0
|
3
|
+
http://www.tokbox.com/
|
4
|
+
|
5
|
+
Copyright 2010, TokBox, Inc.
|
6
|
+
|
7
|
+
Date: November 05 14:50:00 2010
|
8
|
+
=end
|
9
|
+
|
10
|
+
module OpenTok
|
11
|
+
|
12
|
+
# The session object that contains the session_id
|
13
|
+
class Session
|
14
|
+
attr_reader :session_id
|
15
|
+
|
16
|
+
def initialize(session_id)
|
17
|
+
@session_id = session_id
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
session_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/lib/opentok.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
# $:.unshift(File.dirname(__FILE__)) unless
|
2
|
-
# $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
-
|
4
1
|
=begin
|
5
2
|
OpenTok Ruby Library
|
6
3
|
http://www.tokbox.com/
|
@@ -11,7 +8,6 @@
|
|
11
8
|
=end
|
12
9
|
|
13
10
|
module OpenTok
|
14
|
-
|
15
11
|
require 'rubygems'
|
16
12
|
require 'net/http'
|
17
13
|
require 'uri'
|
@@ -21,14 +17,11 @@ module OpenTok
|
|
21
17
|
|
22
18
|
Net::HTTP.version_1_2 # to make sure version 1.2 is used
|
23
19
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
require 'opentok/Exceptions'
|
32
|
-
require 'opentok/OpenTokSDK'
|
33
|
-
|
20
|
+
VERSION = "tbrb-v0.91.2011-02-17"
|
21
|
+
API_URL = "https://staging.tokbox.com/hl"
|
22
|
+
|
23
|
+
require 'monkey_patches'
|
24
|
+
require 'open_tok/exceptions'
|
25
|
+
require 'open_tok/open_tok_sdk'
|
26
|
+
require 'open_tok/session'
|
34
27
|
end
|
data/opentok.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "
|
3
|
+
require "open_tok/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "opentok"
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.email = ["karmenblake@gmail.com"]
|
11
11
|
s.homepage = ""
|
12
12
|
s.summary = %q{OpenTok gem}
|
13
|
-
s.description = %q{OpenTok gem}
|
13
|
+
s.description = %q{OpenTok is a free set of APIs from TokBox that enables websites to weave live group video communication into their online experience. With OpenTok you have the freedom and flexibility to create the most engaging web experience for your users. OpenTok is currently available as a JavaScript and ActionScript 3.0 library. This gem allows you to connect to the API from within Ruby (and Rails)}
|
14
14
|
|
15
15
|
s.rubyforge_project = "opentok"
|
16
16
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OpenTok do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
@api_key = 459782
|
7
|
+
@api_secret = 'b44c3baa32b6476d9d88e8194d0eb1c6b777f76b'
|
8
|
+
@api_staging_url = 'https://staging.tokbox.com/hl'
|
9
|
+
@api_production_url = 'https://api.opentok.com/hl'
|
10
|
+
@host = 'localhost'
|
11
|
+
|
12
|
+
@opentok = OpenTok::OpenTokSDK.new @api_key, @api_secret
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be possible to valid a OpenTokSDK object with a valid key and secret" do
|
16
|
+
@opentok.should be_instance_of OpenTok::OpenTokSDK
|
17
|
+
end
|
18
|
+
|
19
|
+
it "a new OpenTokSDK object should point to the staging environment by default" do
|
20
|
+
@opentok.api_url.should eq @api_staging_url
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "Session creation" do
|
24
|
+
it "should be possible to generate a valid API token with a valid key and secret" do
|
25
|
+
opentok = OpenTok::OpenTokSDK.new @api_key, @api_secret
|
26
|
+
session = opentok.create_session @host
|
27
|
+
|
28
|
+
session.to_s.should match(/\A[0-9a-f]{40}\Z/)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should raise an exception with an invalid key and secret" do
|
32
|
+
opentok = OpenTok::OpenTokSDK.new 0, ''
|
33
|
+
|
34
|
+
expect{
|
35
|
+
session = opentok.create_session @host
|
36
|
+
}.to raise_error OpenTok::OpenTokException
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be possible to set the api url as an option" do
|
40
|
+
opentok = OpenTok::OpenTokSDK.new @api_key, @api_secret, :api_url => @api_production_url
|
41
|
+
|
42
|
+
opentok.api_url.should_not eq @api_staging_url
|
43
|
+
opentok.api_url.should eq @api_production_url
|
44
|
+
|
45
|
+
opentok = OpenTok::OpenTokSDK.new @api_key, @api_secret, :api_url => @api_staging_url
|
46
|
+
|
47
|
+
opentok.api_url.should_not eq @api_production_url
|
48
|
+
opentok.api_url.should eq @api_staging_url
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "Token creation" do
|
53
|
+
before :all do
|
54
|
+
@opentok = OpenTok::OpenTokSDK.new @api_key, @api_secret
|
55
|
+
@valid_session = @opentok.create_session(@host).to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should be possible to create a token" do
|
59
|
+
token = @opentok.generate_token :session_id => @valid_session.to_s
|
60
|
+
|
61
|
+
token.should match(/\A[0-9A-z=]+\Z/)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|