Revision 1298:4f746d8966dd lib/redmine

View differences:

lib/redmine/about.rb
1
module Redmine
2
  class About
3
    def self.print_plugin_info
4
      plugins = Redmine::Plugin.registered_plugins
5

  
6
      if !plugins.empty?
7
        column_with = plugins.map {|internal_name, plugin| plugin.name.length}.max
8
        puts "\nAbout your Redmine plugins"
9

  
10
        plugins.each do |internal_name, plugin|
11
          puts sprintf("%-#{column_with}s   %s", plugin.name, plugin.version)
12
        end
13
      end
14
    end
15
  end
16
end
lib/redmine/access_control.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/access_keys.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/activity.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/activity/fetcher.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/ciphering.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/codeset_util.rb
1
require 'iconv'
1
if RUBY_VERSION < '1.9'
2
  require 'iconv'
3
end
2 4

  
3 5
module Redmine
4 6
  module CodesetUtil
......
100 102
      end
101 103
      encodings = Setting.repositories_encodings.split(',').collect(&:strip)
102 104
      encodings.each do |encoding|
103
        begin
104
          return Iconv.conv('UTF-8', encoding, str)
105
        rescue Iconv::Failure
106
          # do nothing here and try the next encoding
105
        if str.respond_to?(:force_encoding)
106
          begin
107
            str.force_encoding(encoding)
108
            utf8 = str.encode('UTF-8')
109
            return utf8 if utf8.valid_encoding?
110
          rescue
111
            # do nothing here and try the next encoding
112
          end
113
        else
114
          begin
115
            return Iconv.conv('UTF-8', encoding, str)
116
          rescue Iconv::Failure
117
            # do nothing here and try the next encoding
118
          end
107 119
        end
108 120
      end
109 121
      str = self.replace_invalid_utf8(str)
lib/redmine/configuration.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
20 20

  
21 21
    # Configuration default values
22 22
    @defaults = {
23
      'email_delivery' => nil
23
      'email_delivery' => nil,
24
      'max_concurrent_ajax_uploads' => 2
24 25
    }
25 26

  
26 27
    @config = nil
lib/redmine/core_ext/active_record.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
38 38
    end
39 39
  end
40 40
end
41

  
42
class DateValidator < ActiveModel::EachValidator
43
  def validate_each(record, attribute, value)
44
    before_type_cast = record.attributes_before_type_cast[attribute.to_s]
45
    if before_type_cast.is_a?(String) && before_type_cast.present?
46
      # TODO: #*_date_before_type_cast returns a Mysql::Time with ruby1.8+mysql gem
47
      unless before_type_cast =~ /\A\d{4}-\d{2}-\d{2}( 00:00:00)?\z/ && value
48
        record.errors.add attribute, :not_a_date
49
      end
50
    end
51
  end
52
end
lib/redmine/core_ext/date/calculations.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/core_ext/string/conversions.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/core_ext/string/inflections.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/custom_field_format.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/default_data/loader.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
26 26
        # Returns true if no data is already loaded in the database
27 27
        # otherwise false
28 28
        def no_data?
29
          !Role.find(:first, :conditions => {:builtin => 0}) &&
30
            !Tracker.find(:first) &&
31
            !IssueStatus.find(:first) &&
32
            !Enumeration.find(:first)
29
          !Role.where(:builtin => 0).exists? &&
30
            !Tracker.exists? &&
31
            !IssueStatus.exists? &&
32
            !Enumeration.exists?
33 33
        end
34 34

  
35 35
        # Loads the default data
......
139 139
            rejected  = IssueStatus.create!(:name => l(:default_issue_status_rejected), :is_closed => true, :is_default => false, :position => 6)
140 140

  
141 141
            # Workflow
142
            Tracker.find(:all).each { |t|
143
              IssueStatus.find(:all).each { |os|
144
                IssueStatus.find(:all).each { |ns|
142
            Tracker.all.each { |t|
143
              IssueStatus.all.each { |os|
144
                IssueStatus.all.each { |ns|
145 145
                  WorkflowTransition.create!(:tracker_id => t.id, :role_id => manager.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
146 146
                }
147 147
              }
148 148
            }
149 149

  
150
            Tracker.find(:all).each { |t|
150
            Tracker.all.each { |t|
151 151
              [new, in_progress, resolved, feedback].each { |os|
152 152
                [in_progress, resolved, feedback, closed].each { |ns|
153 153
                  WorkflowTransition.create!(:tracker_id => t.id, :role_id => developer.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
......
155 155
              }
156 156
            }
157 157

  
158
            Tracker.find(:all).each { |t|
158
            Tracker.all.each { |t|
159 159
              [new, in_progress, resolved, feedback].each { |os|
160 160
                [closed].each { |ns|
161 161
                  WorkflowTransition.create!(:tracker_id => t.id, :role_id => reporter.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
lib/redmine/export/pdf.rb
1 1
# encoding: utf-8
2 2
#
3 3
# Redmine - project management software
4
# Copyright (C) 2006-2012  Jean-Philippe Lang
4
# Copyright (C) 2006-2013  Jean-Philippe Lang
5 5
#
6 6
# This program is free software; you can redistribute it and/or
7 7
# modify it under the terms of the GNU General Public License
......
17 17
# along with this program; if not, write to the Free Software
18 18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 19

  
20
require 'iconv'
21 20
require 'tcpdf'
22 21
require 'fpdf/chinese'
23 22
require 'fpdf/japanese'
24 23
require 'fpdf/korean'
25 24

  
25
if RUBY_VERSION < '1.9'
26
  require 'iconv'
27
end
28

  
26 29
module Redmine
27 30
  module Export
28 31
    module PDF
......
86 89

  
87 90
        def SetTitle(txt)
88 91
          txt = begin
89
            utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
92
            utf16txt = to_utf16(txt)
90 93
            hextxt = "<FEFF"  # FEFF is BOM
91 94
            hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
92 95
            hextxt << ">"
......
116 119
          html
117 120
        end
118 121

  
122
        # Encodes an UTF-8 string to UTF-16BE
123
        def to_utf16(str)
124
          if str.respond_to?(:encode)
125
            str.encode('UTF-16BE')
126
          else
127
            Iconv.conv('UTF-16BE', 'UTF-8', str)
128
          end
129
        end
130

  
119 131
        def RDMCell(w ,h=0, txt='', border=0, ln=0, align='', fill=0, link='')
120 132
          Cell(w, h, fix_text_encoding(txt), border, ln, align, fill, link)
121 133
        end
......
160 172

  
161 173
        def bookmark_title(txt)
162 174
          txt = begin
163
            utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
175
            utf16txt = to_utf16(txt)
164 176
            hextxt = "<FEFF"  # FEFF is BOM
165 177
            hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
166 178
            hextxt << ">"
......
368 380
        col_width
369 381
      end
370 382

  
371
      def render_table_header(pdf, query, col_width, row_height, col_id_width, table_width)
383
      def render_table_header(pdf, query, col_width, row_height, table_width)
372 384
        # headers
373 385
        pdf.SetFontStyle('B',8)
374 386
        pdf.SetFillColor(230, 230, 230)
......
377 389
        base_x = pdf.GetX
378 390
        base_y = pdf.GetY
379 391
        max_height = issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
380
        pdf.Rect(base_x, base_y, table_width + col_id_width, max_height, 'FD');
392
        pdf.Rect(base_x, base_y, table_width, max_height, 'FD');
381 393
        pdf.SetXY(base_x, base_y);
382 394

  
383 395
        # write the cells on page
384
        pdf.RDMCell(col_id_width, row_height, "#", "T", 0, 'C', 1)
385 396
        issues_to_pdf_write_cells(pdf, query.inline_columns, col_width, row_height, true)
386
        issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width)
397
        issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
387 398
        pdf.SetY(base_y + max_height);
388 399

  
389 400
        # rows
......
405 416
        # Landscape A4 = 210 x 297 mm
406 417
        page_height   = 210
407 418
        page_width    = 297
419
        left_margin   = 10
408 420
        right_margin  = 10
409 421
        bottom_margin = 20
410
        col_id_width  = 10
411 422
        row_height    = 4
412 423

  
413 424
        # column widths
414
        table_width = page_width - right_margin - 10  # fixed left margin
425
        table_width = page_width - right_margin - left_margin
415 426
        col_width = []
416 427
        unless query.inline_columns.empty?
417
          col_width = calc_col_width(issues, query, table_width - col_id_width, pdf)
428
          col_width = calc_col_width(issues, query, table_width, pdf)
418 429
          table_width = col_width.inject(0) {|s,v| s += v}
419 430
        end
420 431

  
421
				# use full width if the description is displayed
432
        # use full width if the description is displayed
422 433
        if table_width > 0 && query.has_column?(:description)
423
          col_width = col_width.map {|w| w = w * (page_width - right_margin - 10 - col_id_width) / table_width}
434
          col_width = col_width.map {|w| w * (page_width - right_margin - left_margin) / table_width}
424 435
          table_width = col_width.inject(0) {|s,v| s += v}
425 436
        end
426 437

  
......
428 439
        pdf.SetFontStyle('B',11)
429 440
        pdf.RDMCell(190,10, title)
430 441
        pdf.Ln
431
        render_table_header(pdf, query, col_width, row_height, col_id_width, table_width)
442
        render_table_header(pdf, query, col_width, row_height, table_width)
432 443
        previous_group = false
433 444
        issue_list(issues) do |issue, level|
434 445
          if query.grouped? &&
......
437 448
            group_label = group.blank? ? 'None' : group.to_s.dup
438 449
            group_label << " (#{query.issue_count_by_group[group]})"
439 450
            pdf.Bookmark group_label, 0, -1
440
            pdf.RDMCell(table_width + col_id_width, row_height * 2, group_label, 1, 1, 'L')
451
            pdf.RDMCell(table_width, row_height * 2, group_label, 1, 1, 'L')
441 452
            pdf.SetFontStyle('',8)
442 453
            previous_group = group
443 454
          end
......
456 467
          space_left = page_height - base_y - bottom_margin
457 468
          if max_height > space_left
458 469
            pdf.AddPage("L")
459
            render_table_header(pdf, query, col_width, row_height, col_id_width, table_width)
470
            render_table_header(pdf, query, col_width, row_height, table_width)
460 471
            base_x = pdf.GetX
461 472
            base_y = pdf.GetY
462 473
          end
463 474

  
464 475
          # write the cells on page
465
          pdf.RDMCell(col_id_width, row_height, issue.id.to_s, "T", 0, 'C', 1)
466 476
          issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
467
          issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width)
477
          issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, 0, col_width)
468 478
          pdf.SetY(base_y + max_height);
469 479

  
470 480
          if query.has_column?(:description) && issue.description?
......
501 511
      end
502 512

  
503 513
      # Draw lines to close the row (MultiCell border drawing in not uniform)
514
      #
515
      #  parameter "col_id_width" is not used. it is kept for compatibility.
504 516
      def issues_to_pdf_draw_borders(pdf, top_x, top_y, lower_y,
505
                                     id_width, col_widths)
506
        col_x = top_x + id_width
517
                                     col_id_width, col_widths)
518
        col_x = top_x
507 519
        pdf.Line(col_x, top_y, col_x, lower_y)    # id right border
508 520
        col_widths.each do |width|
509 521
          col_x += width
lib/redmine/helpers/calendar.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/helpers/diff.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/helpers/gantt.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
23 23
      include Redmine::I18n
24 24
      include Redmine::Utils::DateCalculation
25 25

  
26
      # Relation types that are rendered
27
      DRAW_TYPES = {
28
        IssueRelation::TYPE_BLOCKS   => { :landscape_margin => 16, :color => '#F34F4F' },
29
        IssueRelation::TYPE_PRECEDES => { :landscape_margin => 20, :color => '#628FEA' }
30
      }.freeze
31

  
26 32
      # :nodoc:
27 33
      # Some utility methods for the PDF export
28 34
      class PDF
......
136 142
        )
137 143
      end
138 144

  
145
      # Returns a hash of the relations between the issues that are present on the gantt
146
      # and that should be displayed, grouped by issue ids.
147
      def relations
148
        return @relations if @relations
149
        if issues.any?
150
          issue_ids = issues.map(&:id)
151
          @relations = IssueRelation.
152
            where(:issue_from_id => issue_ids, :issue_to_id => issue_ids, :relation_type => DRAW_TYPES.keys).
153
            group_by(&:issue_from_id)
154
        else
155
          @relations = {}
156
        end
157
      end
158

  
139 159
      # Return all the project nodes that will be displayed
140 160
      def projects
141 161
        return @projects if @projects
......
277 297
            pdf_task(options, coords, :label => label, :markers => true, :height => 0.8)
278 298
          end
279 299
        else
280
          ActiveRecord::Base.logger.debug "Gantt#line_for_project was not given a project with a start_date"
281 300
          ''
282 301
        end
283 302
      end
......
289 308
          html_class << 'icon icon-package '
290 309
          html_class << (version.behind_schedule? ? 'version-behind-schedule' : '') << " "
291 310
          html_class << (version.overdue? ? 'version-overdue' : '')
311
          html_class << ' version-closed' unless version.open?
312
          if version.start_date && version.due_date && version.completed_pourcent
313
            progress_date = calc_progress_date(version.start_date,
314
                                               version.due_date, version.completed_pourcent)
315
            html_class << ' behind-start-date' if progress_date < self.date_from
316
            html_class << ' over-end-date' if progress_date > self.date_to
317
          end
292 318
          s = view.link_to_version(version).html_safe
293 319
          subject = view.content_tag(:span, s,
294 320
                                     :class => html_class).html_safe
295
          html_subject(options, subject, :css => "version-name")
321
          html_subject(options, subject, :css => "version-name",
322
                       :id => "version-#{version.id}")
296 323
        when :image
297 324
          image_subject(options, version.to_s_with_project)
298 325
        when :pdf
......
303 330

  
304 331
      def line_for_version(version, options)
305 332
        # Skip versions that don't have a start_date
306
        if version.is_a?(Version) && version.start_date && version.due_date
333
        if version.is_a?(Version) && version.due_date && version.start_date
307 334
          options[:zoom] ||= 1
308 335
          options[:g_width] ||= (self.date_to - self.date_from + 1) * options[:zoom]
309 336
          coords = coordinates(version.start_date,
310
                               version.due_date, version.completed_pourcent,
337
                               version.due_date, version.completed_percent,
311 338
                               options[:zoom])
312
          label = "#{h version} #{h version.completed_pourcent.to_i.to_s}%"
339
          label = "#{h version} #{h version.completed_percent.to_i.to_s}%"
313 340
          label = h("#{version.project} -") + label unless @project && @project == version.project
314 341
          case options[:format]
315 342
          when :html
316
            html_task(options, coords, :css => "version task", :label => label, :markers => true)
343
            html_task(options, coords, :css => "version task",
344
                      :label => label, :markers => true, :version => version)
317 345
          when :image
318 346
            image_task(options, coords, :label => label, :markers => true, :height => 3)
319 347
          when :pdf
320 348
            pdf_task(options, coords, :label => label, :markers => true, :height => 0.8)
321 349
          end
322 350
        else
323
          ActiveRecord::Base.logger.debug "Gantt#line_for_version was not given a version with a start_date"
324 351
          ''
325 352
        end
326 353
      end
......
336 363
          css_classes << ' issue-overdue' if issue.overdue?
337 364
          css_classes << ' issue-behind-schedule' if issue.behind_schedule?
338 365
          css_classes << ' icon icon-issue' unless Setting.gravatar_enabled? && issue.assigned_to
366
          css_classes << ' issue-closed' if issue.closed?
367
          if issue.start_date && issue.due_before && issue.done_ratio
368
            progress_date = calc_progress_date(issue.start_date,
369
                                               issue.due_before, issue.done_ratio)
370
            css_classes << ' behind-start-date' if progress_date < self.date_from
371
            css_classes << ' over-end-date' if progress_date > self.date_to
372
          end
339 373
          s = "".html_safe
340 374
          if issue.assigned_to.present?
341 375
            assigned_string = l(:field_assigned_to) + ": " + issue.assigned_to.name
......
347 381
          s << view.link_to_issue(issue).html_safe
348 382
          subject = view.content_tag(:span, s, :class => css_classes).html_safe
349 383
          html_subject(options, subject, :css => "issue-subject",
350
                       :title => issue.subject) + "\n"
384
                       :title => issue.subject, :id => "issue-#{issue.id}") + "\n"
351 385
        when :image
352 386
          image_subject(options, issue.subject)
353 387
        when :pdf
......
378 412
            pdf_task(options, coords, :label => label)
379 413
        end
380 414
        else
381
          ActiveRecord::Base.logger.debug "GanttHelper#line_for_issue was not given an issue with a due_before"
382 415
          ''
383 416
        end
384 417
      end
......
611 644
            coords[:bar_end] = self.date_to - self.date_from + 1
612 645
          end
613 646
          if progress
614
            progress_date = start_date + (end_date - start_date + 1) * (progress / 100.0)
647
            progress_date = calc_progress_date(start_date, end_date, progress)
615 648
            if progress_date > self.date_from && progress_date > start_date
616 649
              if progress_date < self.date_to
617 650
                coords[:bar_progress_end] = progress_date - self.date_from
......
638 671
        coords
639 672
      end
640 673

  
641
      # Sorts a collection of issues by start_date, due_date, id for gantt rendering
674
      def calc_progress_date(start_date, end_date, progress)
675
        start_date + (end_date - start_date + 1) * (progress / 100.0)
676
      end
677

  
678
      # TODO: Sorts a collection of issues by start_date, due_date, id for gantt rendering
642 679
      def sort_issues!(issues)
643 680
        issues.sort! { |a, b| gantt_issue_compare(a, b) }
644 681
      end
......
678 715
      def html_subject(params, subject, options={})
679 716
        style = "position: absolute;top:#{params[:top]}px;left:#{params[:indent]}px;"
680 717
        style << "width:#{params[:subject_width] - params[:indent]}px;" if params[:subject_width]
681
        output = view.content_tag('div', subject,
718
        output = view.content_tag(:div, subject,
682 719
                                  :class => options[:css], :style => style,
683
                                  :title => options[:title])
720
                                  :title => options[:title],
721
                                  :id => options[:id])
684 722
        @subjects << output
685 723
        output
686 724
      end
......
705 743
        params[:image].text(params[:indent], params[:top] + 2, subject)
706 744
      end
707 745

  
746
      def issue_relations(issue)
747
        rels = {}
748
        if relations[issue.id]
749
          relations[issue.id].each do |relation|
750
            (rels[relation.relation_type] ||= []) << relation.issue_to_id
751
          end
752
        end
753
        rels
754
      end
755

  
708 756
      def html_task(params, coords, options={})
709 757
        output = ''
710 758
        # Renders the task bar, with progress and late
......
714 762
          style << "top:#{params[:top]}px;"
715 763
          style << "left:#{coords[:bar_start]}px;"
716 764
          style << "width:#{width}px;"
717
          output << view.content_tag(:div, '&nbsp;'.html_safe,
718
                                     :style => style,
719
                                     :class => "#{options[:css]} task_todo")
765
          html_id = "task-todo-issue-#{options[:issue].id}" if options[:issue]
766
          html_id = "task-todo-version-#{options[:version].id}" if options[:version]
767
          content_opt = {:style => style,
768
                         :class => "#{options[:css]} task_todo",
769
                         :id => html_id}
770
          if options[:issue]
771
            rels = issue_relations(options[:issue])
772
            if rels.present?
773
              content_opt[:data] = {"rels" => rels.to_json}
774
            end
775
          end
776
          output << view.content_tag(:div, '&nbsp;'.html_safe, content_opt)
720 777
          if coords[:bar_late_end]
721 778
            width = coords[:bar_late_end] - coords[:bar_start] - 2
722 779
            style = ""
......
733 790
            style << "top:#{params[:top]}px;"
734 791
            style << "left:#{coords[:bar_start]}px;"
735 792
            style << "width:#{width}px;"
793
            html_id = "task-done-issue-#{options[:issue].id}" if options[:issue]
794
            html_id = "task-done-version-#{options[:version].id}" if options[:version]
736 795
            output << view.content_tag(:div, '&nbsp;'.html_safe,
737 796
                                       :style => style,
738
                                       :class => "#{options[:css]} task_done")
797
                                       :class => "#{options[:css]} task_done",
798
                                       :id => html_id)
739 799
          end
740 800
        end
741 801
        # Renders the markers
lib/redmine/helpers/time_report.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
18 18
module Redmine
19 19
  module Helpers
20 20
    class TimeReport
21
      attr_reader :criteria, :columns, :from, :to, :hours, :total_hours, :periods
21
      attr_reader :criteria, :columns, :hours, :total_hours, :periods
22 22

  
23
      def initialize(project, issue, criteria, columns, from, to)
23
      def initialize(project, issue, criteria, columns, time_entry_scope)
24 24
        @project = project
25 25
        @issue = issue
26 26

  
......
30 30
        @criteria = @criteria[0,3]
31 31

  
32 32
        @columns = (columns && %w(year month week day).include?(columns)) ? columns : 'month'
33
        @from = from
34
        @to = to
33
        @scope = time_entry_scope
35 34

  
36 35
        run
37 36
      end
......
44 43

  
45 44
      def run
46 45
        unless @criteria.empty?
47
          scope = TimeEntry.visible.spent_between(@from, @to)
48
          if @issue
49
            scope = scope.on_issue(@issue)
50
          elsif @project
51
            scope = scope.on_project(@project, Setting.display_subprojects_issues?)
52
          end
53 46
          time_columns = %w(tyear tmonth tweek spent_on)
54 47
          @hours = []
55
          scope.sum(:hours, :include => :issue, :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns).each do |hash, hours|
48
          @scope.sum(:hours,
49
              :include => [:issue, :activity],
50
              :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns,
51
              :joins => @criteria.collect{|criteria| @available_criteria[criteria][:joins]}.compact).each do |hash, hours|
56 52
            h = {'hours' => hours}
57 53
            (@criteria + time_columns).each_with_index do |name, i|
58 54
              h[name] = hash[i]
......
67 63
            when 'month'
68 64
              row['month'] = "#{row['tyear']}-#{row['tmonth']}"
69 65
            when 'week'
70
              row['week'] = "#{row['tyear']}-#{row['tweek']}"
66
              row['week'] = "#{row['spent_on'].cwyear}-#{row['tweek']}"
71 67
            when 'day'
72 68
              row['day'] = "#{row['spent_on']}"
73 69
            end
74 70
          end
75 71
          
76
          if @from.nil?
77
            min = @hours.collect {|row| row['spent_on']}.min
78
            @from = min ? min.to_date : Date.today
79
          end
72
          min = @hours.collect {|row| row['spent_on']}.min
73
          @from = min ? min.to_date : Date.today
80 74

  
81
          if @to.nil?
82
            max = @hours.collect {|row| row['spent_on']}.max
83
            @to = max ? max.to_date : Date.today
84
          end
75
          max = @hours.collect {|row| row['spent_on']}.max
76
          @to = max ? max.to_date : Date.today
85 77
          
86 78
          @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
87 79

  
......
98 90
              @periods << "#{date_from.year}-#{date_from.month}"
99 91
              date_from = (date_from + 1.month).at_beginning_of_month
100 92
            when 'week'
101
              @periods << "#{date_from.year}-#{date_from.to_date.cweek}"
93
              @periods << "#{date_from.to_date.cwyear}-#{date_from.to_date.cweek}"
102 94
              date_from = (date_from + 7.day).at_beginning_of_week
103 95
            when 'day'
104 96
              @periods << "#{date_from.to_date}"
......
121 113
                                 'category' => {:sql => "#{Issue.table_name}.category_id",
122 114
                                                :klass => IssueCategory,
123 115
                                                :label => :field_category},
124
                                 'member' => {:sql => "#{TimeEntry.table_name}.user_id",
116
                                 'user' => {:sql => "#{TimeEntry.table_name}.user_id",
125 117
                                             :klass => User,
126
                                             :label => :label_member},
118
                                             :label => :label_user},
127 119
                                 'tracker' => {:sql => "#{Issue.table_name}.tracker_id",
128 120
                                              :klass => Tracker,
129 121
                                              :label => :label_tracker},
......
135 127
                                             :label => :label_issue}
136 128
                               }
137 129

  
130
        # Add time entry custom fields
131
        custom_fields = TimeEntryCustomField.all
132
        # Add project custom fields
133
        custom_fields += ProjectCustomField.all
134
        # Add issue custom fields
135
        custom_fields += (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
136
        # Add time entry activity custom fields
137
        custom_fields += TimeEntryActivityCustomField.all
138

  
138 139
        # Add list and boolean custom fields as available criteria
139
        custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
140 140
        custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
141
          @available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id ORDER BY c.value LIMIT 1)",
142
                                                 :format => cf.field_format,
143
                                                 :label => cf.name}
144
        end if @project
145

  
146
        # Add list and boolean time entry custom fields
147
        TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
148
          @available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id ORDER BY c.value LIMIT 1)",
149
                                                 :format => cf.field_format,
150
                                                 :label => cf.name}
151
        end
152

  
153
        # Add list and boolean time entry activity custom fields
154
        TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
155
          @available_criteria["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id ORDER BY c.value LIMIT 1)",
141
          @available_criteria["cf_#{cf.id}"] = {:sql => "#{cf.join_alias}.value",
142
                                                 :joins => cf.join_for_order_statement,
156 143
                                                 :format => cf.field_format,
157 144
                                                 :label => cf.name}
158 145
        end
lib/redmine/hook.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/i18n.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/imap.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/menu_manager.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
190 190

  
191 191
      # Checks if a user is allowed to access the menu item by:
192 192
      #
193
      # * Checking the url target (project only)
193 194
      # * Checking the conditions of the item
194
      # * Checking the url target (project only)
195 195
      def allowed_node?(node, user, project)
196
        if project && user && !user.allowed_to?(node.url, project)
197
          return false
198
        end
196 199
        if node.condition && !node.condition.call(project)
197 200
          # Condition that doesn't pass
198 201
          return false
199 202
        end
200

  
201
        if project
202
          return user && user.allowed_to?(node.url, project)
203
        else
204
          # outside a project, all menu items allowed
205
          return true
206
        end
203
        return true
207 204
      end
208 205
    end
209 206

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

  
20
module Redmine
21
  module Pagination
22
    class Paginator
23
      attr_reader :item_count, :per_page, :page, :page_param
24

  
25
      def initialize(*args)
26
        if args.first.is_a?(ActionController::Base)
27
          args.shift
28
          ActiveSupport::Deprecation.warn "Paginator no longer takes a controller instance as the first argument. Remove it from #new arguments."
29
        end
30
        item_count, per_page, page, page_param = *args
31

  
32
        @item_count = item_count
33
        @per_page = per_page
34
        page = (page || 1).to_i
35
        if page < 1
36
          page = 1
37
        end
38
        @page = page
39
        @page_param = page_param || :page
40
      end
41

  
42
      def offset
43
        (page - 1) * per_page
44
      end
45

  
46
      def first_page
47
        if item_count > 0
48
          1
49
        end
50
      end
51

  
52
      def previous_page
53
        if page > 1
54
          page - 1
55
        end
56
      end
57

  
58
      def next_page
59
        if last_item < item_count
60
          page + 1
61
        end
62
      end
63

  
64
      def last_page
65
        if item_count > 0
66
          (item_count - 1) / per_page + 1
67
        end
68
      end
69

  
70
      def first_item
71
        item_count == 0 ? 0 : (offset + 1)
72
      end
73

  
74
      def last_item
75
        l = first_item + per_page - 1
76
        l > item_count ? item_count : l
77
      end
78

  
79
      def linked_pages
80
        pages = []
81
        if item_count > 0
82
          pages += [first_page, page, last_page]
83
          pages += ((page-2)..(page+2)).to_a.select {|p| p > first_page && p < last_page}
84
        end
85
        pages = pages.compact.uniq.sort
86
        if pages.size > 1
87
          pages
88
        else
89
          []
90
        end
91
      end
92

  
93
      def items_per_page
94
        ActiveSupport::Deprecation.warn "Paginator#items_per_page will be removed. Use #per_page instead."
95
        per_page
96
      end
97

  
98
      def current
99
        ActiveSupport::Deprecation.warn "Paginator#current will be removed. Use .offset instead of .current.offset."
100
        self
101
      end
102
    end
103

  
104
    # Paginates the given scope or model. Returns a Paginator instance and
105
    # the collection of objects for the current page.
106
    #
107
    # Options:
108
    #   :parameter     name of the page parameter
109
    #
110
    # Examples:
111
    #   @user_pages, @users = paginate User.where(:status => 1)
112
    #
113
    def paginate(scope, options={})
114
      options = options.dup
115
      finder_options = options.extract!(
116
        :conditions,
117
        :order,
118
        :joins,
119
        :include,
120
        :select
121
      )
122
      if scope.is_a?(Symbol) || finder_options.values.compact.any?
123
        return deprecated_paginate(scope, finder_options, options)
124
      end
125

  
126
      paginator = paginator(scope.count, options)
127
      collection = scope.limit(paginator.per_page).offset(paginator.offset).to_a
128

  
129
      return paginator, collection
130
    end
131

  
132
    def deprecated_paginate(arg, finder_options, options={})
133
      ActiveSupport::Deprecation.warn "#paginate with a Symbol and/or find options is depreceted and will be removed. Use a scope instead."
134
      klass = arg.is_a?(Symbol) ? arg.to_s.classify.constantize : arg
135
      scope = klass.scoped(finder_options)
136
      paginate(scope, options)
137
    end
138

  
139
    def paginator(item_count, options={})
140
      options.assert_valid_keys :parameter, :per_page
141

  
142
      page_param = options[:parameter] || :page
143
      page = (params[page_param] || 1).to_i
144
      per_page = options[:per_page] || per_page_option
145
      Paginator.new(item_count, per_page, page, page_param)
146
    end
147

  
148
    module Helper
149
      include Redmine::I18n
150

  
151
      # Renders the pagination links for the given paginator.
152
      #
153
      # Options:
154
      #   :per_page_links    if set to false, the "Per page" links are not rendered
155
      #
156
      def pagination_links_full(*args)
157
        pagination_links_each(*args) do |text, parameters, options|
158
          if block_given?
159
            yield text, parameters, options
160
          else
161
            link_to text, params.merge(parameters), options
162
          end
163
        end
164
      end
165

  
166
      # Yields the given block with the text and parameters
167
      # for each pagination link and returns a string that represents the links
168
      def pagination_links_each(paginator, count=nil, options={}, &block)
169
        options.assert_valid_keys :per_page_links
170

  
171
        per_page_links = options.delete(:per_page_links)
172
        per_page_links = false if count.nil?
173
        page_param = paginator.page_param
174

  
175
        html = ''
176
        if paginator.previous_page
177
          # \xc2\xab(utf-8) = &#171;
178
          text = "\xc2\xab " + l(:label_previous)
179
          html << yield(text, {page_param => paginator.previous_page}, :class => 'previous') + ' '
180
        end
181

  
182
        previous = nil
183
        paginator.linked_pages.each do |page|
184
          if previous && previous != page - 1
185
            html << content_tag('span', '...', :class => 'spacer') + ' '
186
          end
187
          if page == paginator.page
188
            html << content_tag('span', page.to_s, :class => 'current page')
189
          else
190
            html << yield(page.to_s, {page_param => page}, :class => 'page')
191
          end
192
          html << ' '
193
          previous = page
194
        end
195

  
196
        if paginator.next_page
197
          # \xc2\xbb(utf-8) = &#187;
198
          text = l(:label_next) + " \xc2\xbb"
199
          html << yield(text, {page_param => paginator.next_page}, :class => 'next') + ' '
200
        end
201

  
202
        html << content_tag('span', "(#{paginator.first_item}-#{paginator.last_item}/#{paginator.item_count})", :class => 'items') + ' '
203

  
204
        if per_page_links != false && links = per_page_links(paginator, &block)
205
          html << content_tag('span', links.to_s, :class => 'per-page')
206
        end
207

  
208
        html.html_safe
209
      end
210

  
211
      # Renders the "Per page" links.
212
      def per_page_links(paginator, &block)
213
        values = per_page_options(paginator.per_page, paginator.item_count)
214
        if values.any?
215
          links = values.collect do |n|
216
            if n == paginator.per_page
217
              content_tag('span', n.to_s)
218
            else
219
              yield(n, :per_page => n, paginator.page_param => nil)
220
            end
221
          end
222
          l(:label_display_per_page, links.join(', ')).html_safe
223
        end
224
      end
225

  
226
      def per_page_options(selected=nil, item_count=nil)
227
        options = Setting.per_page_options_array
228
        if item_count && options.any?
229
          if item_count > options.first
230
            max = options.detect {|value| value >= item_count} || item_count
231
          else
232
            max = item_count
233
          end
234
          options = options.select {|value| value <= max || value == selected}
235
        end
236
        if options.empty? || (options.size == 1 && options.first == selected)
237
          []
238
        else
239
          options
240
        end
241
      end
242
    end
243
  end
244
end
lib/redmine/platform.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/plugin.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
145 145
      File.join(self.class.public_directory, id.to_s)
146 146
    end
147 147

  
148
    def to_param
149
      id
150
    end
151

  
148 152
    def assets_directory
149 153
      File.join(directory, 'assets')
150 154
    end
lib/redmine/pop3.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/safe_attributes.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/scm/adapters/abstract_adapter.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
17 17

  
18 18
require 'cgi'
19 19

  
20
if RUBY_VERSION < '1.9'
21
  require 'iconv'
22
end
23

  
20 24
module Redmine
21 25
  module Scm
22 26
    module Adapters
......
214 218
          Rails.logger
215 219
        end
216 220

  
221
        # Path to the file where scm stderr output is logged
222
        # Returns nil if the log file is not writable
223
        def self.stderr_log_file
224
          if @stderr_log_file.nil?
225
            writable = false
226
            path = Redmine::Configuration['scm_stderr_log_file'].presence
227
            path ||= Rails.root.join("log/#{Rails.env}.scm.stderr.log").to_s
228
            if File.exists?(path)
229
              if File.file?(path) && File.writable?(path) 
230
                writable = true
231
              else
232
                logger.warn("SCM log file (#{path}) is not writable")
233
              end
234
            else
235
              begin
236
                File.open(path, "w") {}
237
                writable = true
238
              rescue => e
239
                logger.warn("SCM log file (#{path}) cannot be created: #{e.message}")
240
              end
241
            end
242
            @stderr_log_file = writable ? path : false
243
          end
244
          @stderr_log_file || nil
245
        end
246

  
217 247
        def self.shellout(cmd, options = {}, &block)
218 248
          if logger && logger.debug?
219 249
            logger.debug "Shelling out: #{strip_credential(cmd)}"
220
          end
221
          if Rails.env == 'development'
222
            # Capture stderr when running in dev environment
223
            cmd = "#{cmd} 2>>#{shell_quote(Rails.root.join('log/scm.stderr.log').to_s)}"
250
            # Capture stderr in a log file
251
            if stderr_log_file
252
              cmd = "#{cmd} 2>>#{shell_quote(stderr_log_file)}"
253
            end
224 254
          end
225 255
          begin
226 256
            mode = "r+"
lib/redmine/scm/adapters/bazaar_adapter.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
104 104
            re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
105 105
            io.each_line do |line|
106 106
              next unless line =~ re
107
              name_locale = $3.strip
107
              name_locale, slash, revision = $3.strip, $4, $5.strip
108 108
              name = scm_iconv('UTF-8', @path_encoding, name_locale)
109 109
              entries << Entry.new({:name => name,
110 110
                                    :path => ((path.empty? ? "" : "#{path}/") + name),
111
                                    :kind => ($4.blank? ? 'file' : 'dir'),
111
                                    :kind => (slash.blank? ? 'file' : 'dir'),
112 112
                                    :size => nil,
113
                                    :lastrev => Revision.new(:revision => $5.strip)
113
                                    :lastrev => Revision.new(:revision => revision)
114 114
                                  })
115 115
            end
116 116
          end
lib/redmine/scm/adapters/darcs_adapter.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/scm/adapters/filesystem_adapter.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# FileSystem adapter
5 5
# File written by Paul Rivier, at Demotera.
lib/redmine/scm/adapters/git_adapter.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/scm/adapters/mercurial_adapter.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/scm/adapters/subversion_adapter.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/scm/base.rb
4 4
      class << self
5 5

  
6 6
        def all
7
          @scms
7
          @scms || []
8 8
        end
9 9

  
10 10
        # Add a new SCM adapter and repository
lib/redmine/search.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/subclass_factory.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/syntax_highlighting.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
33 33

  
34 34
    module CodeRay
35 35
      require 'coderay'
36
      require 'coderay/helpers/file_type'
37 36

  
38 37
      class << self
39 38
        # Highlights +text+ as the content of +filename+
lib/redmine/themes.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/thumbnail.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/unified_diff.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
28 28
      lines = 0
29 29
      @truncated = false
30 30
      diff_table = DiffTable.new(diff_type, diff_style)
31
      diff.each do |line|
32
        line_encoding = nil
33
        if line.respond_to?(:force_encoding)
34
          line_encoding = line.encoding
35
          # TODO: UTF-16 and Japanese CP932 which is imcompatible with ASCII
36
          #       In Japan, diffrence between file path encoding
37
          #       and file contents encoding is popular.
38
          line.force_encoding('ASCII-8BIT')
39
        end
40
        unless diff_table.add_line line
41
          line.force_encoding(line_encoding) if line_encoding
31
      diff.each do |line_raw|
32
        line = Redmine::CodesetUtil.to_utf8_by_setting(line_raw)
33
        unless diff_table.add_line(line)
42 34
          self << diff_table if diff_table.length > 0
43 35
          diff_table = DiffTable.new(diff_type, diff_style)
44 36
        end
......
83 75
          @parsing = true
84 76
        end
85 77
      else
86
        if line =~ /^[^\+\-\s@\\]/
78
        if line =~ %r{^[^\+\-\s@\\]}
87 79
          @parsing = false
88 80
          return false
89 81
        elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
......
207 199
        while starting < max && line_left[starting] == line_right[starting]
208 200
          starting += 1
209 201
        end
202
        if (! "".respond_to?(:force_encoding)) && starting < line_left.size
203
          while line_left[starting].ord.between?(128, 191) && starting > 0
204
            starting -= 1
205
          end
206
        end
210 207
        ending = -1
211 208
        while ending >= -(max - starting) && line_left[ending] == line_right[ending]
212 209
          ending -= 1
213 210
        end
211
        if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size)
212
          while line_left[ending].ord.between?(128, 191) && ending > -1
213
            ending -= 1
214
          end
215
        end
214 216
        unless starting == 0 && ending == -1
215 217
          [starting, ending]
216 218
        end
......
268 270
    private
269 271

  
270 272
    def line_to_html(line, offsets)
273
      html = line_to_html_raw(line, offsets)
274
      html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
275
      html
276
    end
277

  
278
    def line_to_html_raw(line, offsets)
271 279
      if offsets
272 280
        s = ''
273 281
        unless offsets.first == 0
lib/redmine/utils.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/version.rb
3 3
module Redmine
4 4
  module VERSION #:nodoc:
5 5
    MAJOR = 2
6
    MINOR = 2
7
    TINY  = 4
6
    MINOR = 3
7
    TINY  = 1
8 8

  
9 9
    # Branch values:
10 10
    # * official release: nil
lib/redmine/views/api_template_handler.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
lib/redmine/views/builders.rb
1 1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
......
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18
require 'redmine/views/builders/json'
19
require 'redmine/views/builders/xml'
20

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff