Revision 1298:4f746d8966dd .svn/pristine/29

View differences:

.svn/pristine/29/2916f748eef73ff691bcfc74e7c1ac23960d090b.svn-base
1
# $Id: ber.rb 142 2006-07-26 12:20:33Z blackhedd $
2
#
3
# NET::BER
4
# Mixes ASN.1/BER convenience methods into several standard classes.
5
# Also provides BER parsing functionality.
6
#
7
#----------------------------------------------------------------------------
8
#
9
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
10
#
11
# Gmail: garbagecat10
12
#
13
# This program is free software; you can redistribute it and/or modify
14
# it under the terms of the GNU General Public License as published by
15
# the Free Software Foundation; either version 2 of the License, or
16
# (at your option) any later version.
17
#
18
# This program is distributed in the hope that it will be useful,
19
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
# GNU General Public License for more details.
22
#
23
# You should have received a copy of the GNU General Public License
24
# along with this program; if not, write to the Free Software
25
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
26
#
27
#---------------------------------------------------------------------------
28
#
29
#
30

  
31

  
32

  
33

  
34
module Net
35

  
36
  module BER
37

  
38
  class BerError < Exception; end
39

  
40

  
41
  # This module is for mixing into IO and IO-like objects.
42
  module BERParser
43

  
44
    # The order of these follows the class-codes in BER.
45
    # Maybe this should have been a hash.
46
    TagClasses = [:universal, :application, :context_specific, :private]
47

  
48
    BuiltinSyntax = {
49
      :universal => {
50
        :primitive => {
51
          1 => :boolean,
52
          2 => :integer,
53
          4 => :string,
54
          10 => :integer,
55
        },
56
        :constructed => {
57
          16 => :array,
58
          17 => :array
59
        }
60
      }
61
    }
62

  
63
    #
64
    # read_ber
65
    # TODO: clean this up so it works properly with partial
66
    # packets coming from streams that don't block when
67
    # we ask for more data (like StringIOs). At it is,
68
    # this can throw TypeErrors and other nasties.
69
    #
70
    def read_ber syntax=nil
71
      return nil if (StringIO == self.class) and  eof?
72

  
73
      id = getc  # don't trash this value, we'll use it later
74
      tag = id & 31
75
      tag < 31 or raise BerError.new( "unsupported tag encoding: #{id}" )
76
      tagclass = TagClasses[ id >> 6 ]
77
      encoding = (id & 0x20 != 0) ? :constructed : :primitive
78

  
79
      n = getc
80
      lengthlength,contentlength = if n <= 127
81
        [1,n]
82
      else
83
        j = (0...(n & 127)).inject(0) {|mem,x| mem = (mem << 8) + getc}
84
        [1 + (n & 127), j]
85
      end
86

  
87
      newobj = read contentlength
88

  
89
      objtype = nil
90
      [syntax, BuiltinSyntax].each {|syn|
91
        if syn && (ot = syn[tagclass]) && (ot = ot[encoding]) && ot[tag]
92
          objtype = ot[tag]
93
          break
94
        end
95
      }
96
      
97
      obj = case objtype
98
      when :boolean
99
        newobj != "\000"
100
      when :string
101
        (newobj || "").dup
102
      when :integer
103
        j = 0
104
        newobj.each_byte {|b| j = (j << 8) + b}
105
        j
106
      when :array
107
        seq = []
108
        sio = StringIO.new( newobj || "" )
109
        # Interpret the subobject, but note how the loop
110
        # is built: nil ends the loop, but false (a valid
111
        # BER value) does not!
112
        while (e = sio.read_ber(syntax)) != nil
113
          seq << e
114
        end
115
        seq
116
      else
117
        raise BerError.new( "unsupported object type: class=#{tagclass}, encoding=#{encoding}, tag=#{tag}" )
118
      end
119

  
120
      # Add the identifier bits into the object if it's a String or an Array.
121
      # We can't add extra stuff to Fixnums and booleans, not that it makes much sense anyway.
122
      obj and ([String,Array].include? obj.class) and obj.instance_eval "def ber_identifier; #{id}; end"
123
      obj
124

  
125
    end
126

  
127
  end # module BERParser
128
  end # module BER
129

  
130
end # module Net
131

  
132

  
133
class IO
134
  include Net::BER::BERParser
135
end
136

  
137
require "stringio"
138
class StringIO
139
  include Net::BER::BERParser
140
end
141

  
142
begin
143
  require 'openssl'
144
  class OpenSSL::SSL::SSLSocket
145
    include Net::BER::BERParser
146
  end
147
rescue LoadError
148
# Ignore LoadError.
149
# DON'T ignore NameError, which means the SSLSocket class
150
# is somehow unavailable on this implementation of Ruby's openssl.
151
# This may be WRONG, however, because we don't yet know how Ruby's
152
# openssl behaves on machines with no OpenSSL library. I suppose
153
# it's possible they do not fail to require 'openssl' but do not
154
# create the classes. So this code is provisional.
155
# Also, you might think that OpenSSL::SSL::SSLSocket inherits from
156
# IO so we'd pick it up above. But you'd be wrong.
157
end
158

  
159
class String
160
  def read_ber syntax=nil
161
    StringIO.new(self).read_ber(syntax)
162
  end
163
end
164

  
165

  
166

  
167
#----------------------------------------------
168

  
169

  
170
class FalseClass
171
  #
172
  # to_ber
173
  #
174
  def to_ber
175
    "\001\001\000"
176
  end
177
end
178

  
179

  
180
class TrueClass
181
  #
182
  # to_ber
183
  #
184
  def to_ber
185
    "\001\001\001"
186
  end
187
end
188

  
189

  
190

  
191
class Fixnum
192
  #
193
  # to_ber
194
  #
195
  def to_ber
196
    i = [self].pack('w')
197
    [2, i.length].pack("CC") + i
198
  end
199

  
200
  #
201
  # to_ber_enumerated
202
  #
203
  def to_ber_enumerated
204
    i = [self].pack('w')
205
    [10, i.length].pack("CC") + i
206
  end
207

  
208
  #
209
  # to_ber_length_encoding
210
  #
211
  def to_ber_length_encoding
212
    if self <= 127
213
      [self].pack('C')
214
    else
215
      i = [self].pack('N').sub(/^[\0]+/,"")
216
      [0x80 + i.length].pack('C') + i
217
    end
218
  end
219

  
220
end # class Fixnum
221

  
222

  
223
class Bignum
224

  
225
  def to_ber
226
    i = [self].pack('w')
227
    i.length > 126 and raise Net::BER::BerError.new( "range error in bignum" )
228
    [2, i.length].pack("CC") + i
229
  end
230

  
231
end
232

  
233

  
234

  
235
class String
236
  #
237
  # to_ber
238
  # A universal octet-string is tag number 4,
239
  # but others are possible depending on the context, so we
240
  # let the caller give us one.
241
  # The preferred way to do this in user code is via to_ber_application_sring
242
  # and to_ber_contextspecific.
243
  #
244
  def to_ber code = 4
245
    [code].pack('C') + length.to_ber_length_encoding + self
246
  end
247

  
248
  #
249
  # to_ber_application_string
250
  #
251
  def to_ber_application_string code
252
    to_ber( 0x40 + code )
253
  end
254

  
255
  #
256
  # to_ber_contextspecific
257
  #
258
  def to_ber_contextspecific code
259
    to_ber( 0x80 + code )
260
  end
261

  
262
end # class String
263

  
264

  
265

  
266
class Array
267
  #
268
  # to_ber_appsequence
269
  # An application-specific sequence usually gets assigned
270
  # a tag that is meaningful to the particular protocol being used.
271
  # This is different from the universal sequence, which usually
272
  # gets a tag value of 16.
273
  # Now here's an interesting thing: We're adding the X.690
274
  # "application constructed" code at the top of the tag byte (0x60),
275
  # but some clients, notably ldapsearch, send "context-specific
276
  # constructed" (0xA0). The latter would appear to violate RFC-1777,
277
  # but what do I know? We may need to change this.
278
  #
279

  
280
  def to_ber                 id = 0; to_ber_seq_internal( 0x30 + id ); end
281
  def to_ber_set             id = 0; to_ber_seq_internal( 0x31 + id ); end
282
  def to_ber_sequence        id = 0; to_ber_seq_internal( 0x30 + id ); end
283
  def to_ber_appsequence     id = 0; to_ber_seq_internal( 0x60 + id ); end
284
  def to_ber_contextspecific id = 0; to_ber_seq_internal( 0xA0 + id ); end
285

  
286
  private
287
  def to_ber_seq_internal code
288
    s = self.to_s
289
    [code].pack('C') + s.length.to_ber_length_encoding + s
290
  end
291

  
292
end # class Array
293

  
294

  
.svn/pristine/29/299dc6b637e0f5b3775b92631d240971508c0684.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../../../test_helper', __FILE__)
19

  
20
class Redmine::MimeTypeTest < ActiveSupport::TestCase
21

  
22
  def test_of
23
    to_test = {'test.unk' => nil,
24
               'test.txt' => 'text/plain',
25
               'test.c' => 'text/x-c',
26
               }
27
    to_test.each do |name, expected|
28
      assert_equal expected, Redmine::MimeType.of(name)
29
    end
30
  end
31

  
32
  def test_css_class_of
33
    to_test = {'test.unk' => nil,
34
               'test.txt' => 'text-plain',
35
               'test.c' => 'text-x-c',
36
               }
37
    to_test.each do |name, expected|
38
      assert_equal expected, Redmine::MimeType.css_class_of(name)
39
    end
40
  end
41

  
42
  def test_main_mimetype_of
43
    to_test = {'test.unk' => nil,
44
               'test.txt' => 'text',
45
               'test.c' => 'text',
46
               }
47
    to_test.each do |name, expected|
48
      assert_equal expected, Redmine::MimeType.main_mimetype_of(name)
49
    end
50
  end
51

  
52
  def test_is_type
53
    to_test = {['text', 'test.unk'] => false,
54
               ['text', 'test.txt'] => true,
55
               ['text', 'test.c'] => true,
56
               }
57
    to_test.each do |args, expected|
58
      assert_equal expected, Redmine::MimeType.is_type?(*args)
59
    end
60
  end
61
end
.svn/pristine/29/29d1b7a44a44f4040dd2b8d4fe4b9b40b3383592.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
class TrackersController < ApplicationController
19
  layout 'admin'
20

  
21
  before_filter :require_admin, :except => :index
22
  before_filter :require_admin_or_api_request, :only => :index
23
  accept_api_auth :index
24

  
25
  def index
26
    respond_to do |format|
27
      format.html {
28
        @tracker_pages, @trackers = paginate :trackers, :per_page => 10, :order => 'position'
29
        render :action => "index", :layout => false if request.xhr?
30
      }
31
      format.api {
32
        @trackers = Tracker.all
33
      }
34
    end
35
  end
36

  
37
  def new
38
    @tracker ||= Tracker.new(params[:tracker])
39
    @trackers = Tracker.find :all, :order => 'position'
40
    @projects = Project.find(:all)
41
  end
42

  
43
  def create
44
    @tracker = Tracker.new(params[:tracker])
45
    if request.post? and @tracker.save
46
      # workflow copy
47
      if !params[:copy_workflow_from].blank? && (copy_from = Tracker.find_by_id(params[:copy_workflow_from]))
48
        @tracker.workflows.copy(copy_from)
49
      end
50
      flash[:notice] = l(:notice_successful_create)
51
      redirect_to :action => 'index'
52
      return
53
    end
54
    new
55
    render :action => 'new'
56
  end
57

  
58
  def edit
59
    @tracker ||= Tracker.find(params[:id])
60
    @projects = Project.find(:all)
61
  end
62
  
63
  def update
64
    @tracker = Tracker.find(params[:id])
65
    if request.put? and @tracker.update_attributes(params[:tracker])
66
      flash[:notice] = l(:notice_successful_update)
67
      redirect_to :action => 'index'
68
      return
69
    end
70
    edit
71
    render :action => 'edit'
72
  end
73

  
74
  verify :method => :delete, :only => :destroy, :redirect_to => { :action => :index }
75
  def destroy
76
    @tracker = Tracker.find(params[:id])
77
    unless @tracker.issues.empty?
78
      flash[:error] = l(:error_can_not_delete_tracker)
79
    else
80
      @tracker.destroy
81
    end
82
    redirect_to :action => 'index'
83
  end
84
end
.svn/pristine/29/29e480c531a7477e290d81b189c3105531d0d4db.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../base', __FILE__)
19

  
20
class Redmine::UiTest::IssuesTest < Redmine::UiTest::Base
21
  fixtures :projects, :users, :roles, :members, :member_roles,
22
           :trackers, :projects_trackers, :enabled_modules, :issue_statuses, :issues,
23
           :enumerations, :custom_fields, :custom_values, :custom_fields_trackers,
24
           :watchers
25

  
26
  def test_create_issue
27
    log_user('jsmith', 'jsmith')
28
    visit '/projects/ecookbook/issues/new'
29
    within('form#issue-form') do
30
      select 'Bug', :from => 'Tracker'
31
      select 'Low', :from => 'Priority'
32
      fill_in 'Subject', :with => 'new test issue'
33
      fill_in 'Description', :with => 'new issue'
34
      select '0 %', :from => 'Done'
35
      fill_in 'Due date', :with => ''
36
      select '', :from => 'Assignee'
37
      fill_in 'Searchable field', :with => 'Value for field 2'
38
      # click_button 'Create' would match both 'Create' and 'Create and continue' buttons
39
      find('input[name=commit]').click
40
    end
41

  
42
    # find created issue
43
    issue = Issue.find_by_subject("new test issue")
44
    assert_kind_of Issue, issue
45

  
46
    # check redirection
47
    find 'div#flash_notice', :visible => true, :text => "Issue \##{issue.id} created."
48
    assert_equal issue_path(:id => issue), current_path
49

  
50
    # check issue attributes
51
    assert_equal 'jsmith', issue.author.login
52
    assert_equal 1, issue.project.id
53
    assert_equal IssueStatus.find_by_name('New'), issue.status 
54
    assert_equal Tracker.find_by_name('Bug'), issue.tracker
55
    assert_equal IssuePriority.find_by_name('Low'), issue.priority
56
    assert_equal 'Value for field 2', issue.custom_field_value(CustomField.find_by_name('Searchable field'))
57
  end
58

  
59
  def test_create_issue_with_form_update
60
    field1 = IssueCustomField.create!(
61
      :field_format => 'string',
62
      :name => 'Field1',
63
      :is_for_all => true,
64
      :trackers => Tracker.find_all_by_id([1, 2])
65
    )
66
    field2 = IssueCustomField.create!(
67
      :field_format => 'string',
68
      :name => 'Field2',
69
      :is_for_all => true,
70
      :trackers => Tracker.find_all_by_id(2)
71
    )
72

  
73
    Role.non_member.add_permission! :add_issues
74
    Role.non_member.remove_permission! :edit_issues, :add_issue_notes
75

  
76
    log_user('someone', 'foo')
77
    visit '/projects/ecookbook/issues/new'
78
    assert page.has_no_content?(field2.name)
79
    assert page.has_content?(field1.name)
80

  
81
    fill_in 'Subject', :with => 'New test issue'
82
    fill_in 'Description', :with => 'New test issue description'
83
    fill_in field1.name, :with => 'CF1 value'
84
    select 'Low', :from => 'Priority'
85

  
86
    # field2 should show up when changing tracker
87
    select 'Feature request', :from => 'Tracker'
88
    assert page.has_content?(field2.name)
89
    assert page.has_content?(field1.name)
90

  
91
    fill_in field2.name, :with => 'CF2 value'
92
    assert_difference 'Issue.count' do
93
      page.first(:button, 'Create').click
94
    end
95

  
96
    issue = Issue.order('id desc').first
97
    assert_equal 'New test issue', issue.subject
98
    assert_equal 'New test issue description', issue.description
99
    assert_equal 'Low', issue.priority.name
100
    assert_equal 'CF1 value', issue.custom_field_value(field1)
101
    assert_equal 'CF2 value', issue.custom_field_value(field2)
102
  end
103

  
104
  def test_create_issue_with_watchers
105
    User.generate!(:firstname => 'Some', :lastname => 'Watcher')
106

  
107
    log_user('jsmith', 'jsmith')
108
    visit '/projects/ecookbook/issues/new'
109
    fill_in 'Subject', :with => 'Issue with watchers'
110
    # Add a project member as watcher
111
    check 'Dave Lopper'
112
    # Search for another user
113
    click_link 'Search for watchers to add'
114
    within('form#new-watcher-form') do
115
      assert page.has_content?('Some One')
116
      fill_in 'user_search', :with => 'watch'
117
      assert page.has_no_content?('Some One')
118
      check 'Some Watcher'
119
      click_button 'Add'
120
    end
121
    assert_difference 'Issue.count' do
122
      find('input[name=commit]').click
123
    end
124

  
125
    issue = Issue.order('id desc').first
126
    assert_equal ['Dave Lopper', 'Some Watcher'], issue.watcher_users.map(&:name).sort
127
  end
128

  
129
  def test_preview_issue_description
130
    log_user('jsmith', 'jsmith')
131
    visit '/projects/ecookbook/issues/new'
132
    within('form#issue-form') do
133
      fill_in 'Subject', :with => 'new issue subject'
134
      fill_in 'Description', :with => 'new issue description'
135
      click_link 'Preview'
136
    end
137
    find 'div#preview fieldset', :visible => true, :text => 'new issue description'
138
    assert_difference 'Issue.count' do
139
      find('input[name=commit]').click
140
    end
141

  
142
    issue = Issue.order('id desc').first
143
    assert_equal 'new issue description', issue.description
144
  end
145

  
146
  def test_update_issue_with_form_update
147
    field = IssueCustomField.create!(
148
      :field_format => 'string',
149
      :name => 'Form update CF',
150
      :is_for_all => true,
151
      :trackers => Tracker.find_all_by_name('Feature request')
152
    )
153

  
154
    Role.non_member.add_permission! :edit_issues
155
    Role.non_member.remove_permission! :add_issues, :add_issue_notes
156

  
157
    log_user('someone', 'foo')
158
    visit '/issues/1'
159
    assert page.has_no_content?('Form update CF')
160

  
161
    page.first(:link, 'Update').click
162
    # the custom field should show up when changing tracker
163
    select 'Feature request', :from => 'Tracker'
164
    assert page.has_content?('Form update CF')
165

  
166
    fill_in 'Form update', :with => 'CF value'
167
    assert_no_difference 'Issue.count' do
168
      page.first(:button, 'Submit').click
169
    end
170

  
171
    issue = Issue.find(1)
172
    assert_equal 'CF value', issue.custom_field_value(field)
173
  end
174

  
175
  def test_remove_issue_watcher_from_sidebar
176
    user = User.find(3)
177
    Watcher.create!(:watchable => Issue.find(1), :user => user)
178

  
179
    log_user('jsmith', 'jsmith')
180
    visit '/issues/1'
181
    assert page.first('#sidebar').has_content?('Watchers (1)')
182
    assert page.first('#sidebar').has_content?(user.name)
183
    assert_difference 'Watcher.count', -1 do
184
      page.first('ul.watchers .user-3 a.delete').click
185
    end
186
    assert page.first('#sidebar').has_content?('Watchers (0)')
187
    assert page.first('#sidebar').has_no_content?(user.name)
188
  end
189

  
190
  def test_watch_issue_via_context_menu
191
    log_user('jsmith', 'jsmith')
192
    visit '/issues'
193
    find('tr#issue-1 td.updated_on').click
194
    page.execute_script "$('tr#issue-1 td.updated_on').trigger('contextmenu');"
195
    assert_difference 'Watcher.count' do
196
      within('#context-menu') do
197
        click_link 'Watch'
198
      end
199
    end
200
    assert Issue.find(1).watched_by?(User.find_by_login('jsmith'))
201
  end
202

  
203
  def test_bulk_watch_issues_via_context_menu
204
    log_user('jsmith', 'jsmith')
205
    visit '/issues'
206
    find('tr#issue-1 input[type=checkbox]').click
207
    find('tr#issue-4 input[type=checkbox]').click
208
    page.execute_script "$('tr#issue-1 td.updated_on').trigger('contextmenu');"
209
    assert_difference 'Watcher.count', 2 do
210
      within('#context-menu') do
211
        click_link 'Watch'
212
      end
213
    end
214
    assert Issue.find(1).watched_by?(User.find_by_login('jsmith'))
215
    assert Issue.find(4).watched_by?(User.find_by_login('jsmith'))
216
  end
217
end

Also available in: Unified diff