riboseinc/ruby-vobject

View on GitHub
lib/vobject/vcard/v4_0/paramcheck.rb

Summary

Maintainability
F
3 days
Test Coverage
require "set"
require "uri"
require "date"
include Rsec::Helpers
require "vobject"

module Vcard::V4_0
  class Paramcheck
    class << self
      def paramcheck(strict, prop, params, ctx)
        errors = []
        if params && params[:TYPE]
          case prop
          when :FN, :NICKNAME, :PHOTO, :ADR, :TEL, :EMAIL, :IMPP, :LANG, :TZ,
            :GEO, :TITLE, :ROLE, :LOGO, :ORG, :RELATED, :CATEGORIES, :NOTE,
            :SOUND, :URL, :KEY, :FBURL, :CALADRURI, :CALURI, :EXPERTISE,
            :HOBBY, :INTEREST, :ORG_DIRECTORY
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":TYPE parameter given for #{prop}", ctx)
          end
        end
        if params && params[:MEDIATYPE]
          case prop
          when :SOURCE, :PHOTO, :IMPP, :GEO, :LOGO, :MEMBER, :SOUND, :URL,
            :FBURL, :CALADRURI, :CALURI, :UID, :TZ
            # no-op
          when :TEL, :KEY
            if params[:VALUE] == "uri"
            else
              parse_err(strict, errors, ":MEDIATYPE parameter given for #{prop} with :VALUE of text", ctx)
            end
          when :RELATED
            if params[:VALUE] == "text"
              parse_err(strict, errors, ":MEDIATYPE parameter given for #{prop} with :VALUE of text", ctx)
            end
          when /^x/i
          else
            parse_err(strict, errors, ":MEDIATYPE parameter given for #{prop}", ctx)
          end
        end
        if params && params[:CALSCALE]
          case prop
          when :BDAY, :ANNIVERSARY
            # no-op
          when :DEATHDATE
            if params[:VALUE] == "text"
              parse_err(strict, errors, ":CALSCALE parameter given for #{prop} with :VALUE of text", ctx)
            end
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":CALSCALE parameter given for #{prop}", ctx)
          end
        end
        if params && params[:GEO]
          case prop
          when :ADR
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":GEO parameter given for #{prop}", ctx)
          end
        end
        if params && params[:TZ]
          case prop
          when :ADR
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":TZ parameter given for #{prop}", ctx)
          end
        end
        if params && params[:LANGUAGE]
          case prop
          when :FN, :N, :NICKNAME, :ADR, :TITLE, :ROLE, :LOGO, :ORG, :NOTE,
            :SOUND, :BIRTHPLACE, :DEATHPLACE, :EXPERTISE, :HOBBY, :INTEREST, :ORG_DIRECTORY
            # no-op
          when :BDAY, :ANNIVERSARY, :DEATHDATE
            # added :ANNIVERSARY per errata
            if params[:VALUE] == "text"
            else
              parse_err(strict, errors, ":LANGUAGE parameter given for #{prop} with :VALUE of date/time", ctx)
            end
          when :RELATED
            if params[:VALUE] == "text"
            else
              parse_err(strict, errors, ":LANGUAGE parameter given for #{prop} with :VALUE of uri", ctx)
            end
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":LANGUAGE parameter given for #{prop}", ctx)
          end
        end
        if params && params[:VALUE]
          case prop
          when :SOURCE, :KIND, :XML, :FN, :N, :NICKNAME, :PHOTO, :GENDER, :ADR,
            :TEL, :EMAIL, :IMPP, :LANG, :TZ, :GEO, :TITLE, :ROLE, :LOGO, :ORG,
            :MEMBER, :RELATED, :CATEGORIES, :NOTE, :PRODID, :REV, :SOUND, :URL, :VERSION,
            :KEY, :FBURL, :CALADRURI, :CALURI, :BDAY, :ANNIVERSARY, :BIRTHPLACE,
            :DEATHPLACE, :DEATHDATE
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":VALUE parameter given for #{prop}", ctx)
          end
        end
        if params && params[:PREF]
          case prop
          when :SOURCE, :FN, :NICKNAME, :PHOTO, :ADR, :TEL, :EMAIL, :IMPP, :LANG,
            :TZ, :GEO, :TITLE, :ROLE, :LOGO, :ORG, :MEMBER, :RELATED, :CATEGORIES,
            :NOTE, :SOUND, :URL, :KEY, :FBURL, :CALADRURI, :CALURI, :EXPERTISE,
            :HOBBY, :INTEREST, :ORG_DIRECTORY, :ORG_DIRECTORY
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":PREF parameter given for #{prop}", ctx)
          end
        end
        if params && params[:PID]
          case prop
          when :SOURCE, :FN, :NICKNAME, :PHOTO, :ADR, :TEL, :EMAIL, :IMPP, :LANG,
            :TZ, :GEO, :TITLE, :ROLE, :LOGO, :ORG, :MEMBER, :RELATED, :CATEGORIES,
            :NOTE, :SOUND, :URL, :KEY, :FBURL, :CALADRURI, :CALURI, :ORG_DIRECTORY
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":PID parameter given for #{prop}", ctx)
          end
        end
        if params && params[:SORT_AS]
          case prop
          when :N, :ORG
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":SORT_AS parameter given for #{prop}", ctx)
          end
        end
        if params && params[:ALTID]
          case prop
          when :SOURCE, :XML, :FN, :N, :NICKNAME, :PHOTO, :BDAY, :ANNIVERSARY, :ADR,
            :TEL, :EMAIL, :IMPP, :LANG, :TZ, :GEO, :TITLE, :ROLE, :LOGO, :ORG, :MEMBER,
            :RELATED, :CATEGORIES, :NOTE, :SOUND, :URL, :KEY, :FBURL, :CALADRURI, :CALURI,
            :BIRTHPLACE, :DEATHPLACE, :DEATHDATE, :EXPERTISE, :HOBBY, :INTEREST, :ORG_DIRECTORY
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":SOURCE parameter given for #{prop}", ctx)
          end
        end
        if params && params[:LABEL]
          case prop
          when :ADR
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":LABEL parameter given for #{prop}", ctx)
          end
        end
        if params && params[:LEVEL]
          case prop
          when :EXPERTISE, :HOBBY, :INTEREST
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":LEVEL parameter given for #{prop}", ctx)
          end
        end
        if params && params[:INDEX]
          case prop
          when :EXPERTISE, :HOBBY, :INTEREST, :ORG_DIRECTORY
            # no-op
          when /^x/i
            # no-op
          else
            parse_err(strict, errors, ":INDEX parameter given for #{prop}", ctx)
          end
        end
        params.each do |p|
          case p
          when :LANGUAGE, :VALUE, :PREF, :PID, :TYPE, :GEO, :TZ, :SORT_AS, :CALSCALE,
            :LABEL, :ALTID
            # no-op
          when /^x/i
            # xname parameters are always allowed
          else
            # any-param
            case prop
            when :SOURCE, :KIND, :FN, :N, :NICKNAME, :PHOTO, :BDAY, :ANNIVERSARY, :GENDER,
              :ADR, :TEL, :EMAIL, :IMPP, :LANG, :TZ, :GEO, :TITLE, :ROLE, :LOGO, :ORG, :MEMBER,
              :RELATED, :CATEGORIES, :NOTE, :PRODID, :REV, :SOUND, :UID, :CLIENTPIDMAP, :URL,
              :VERSION, :KEY, :FBURL, :CALADRURI, :CALURI, :BIRTHPLACE, :DEATHPLACE, :DEATHDATE,
              :EXPERTISE, :HOBBY, :INTEREST, :ORG_DIRECTORY
              # no-op
            when /^x/i
              # no-op
            else
              parse_err(strict, errors, "#{p} parameter given for #{prop}", ctx)
            end
          end
        end
        case prop
        when :SOURCE, :PHOTO, :IMPP, :GEO, :LOGO, :MEMBER, :SOUND, :URL, :FBURL,
          :CALADRURI, :CALURI
          params.each do |key, val|
            parse_err(strict, errors, "illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val != "uri"
          end
        when :LANG
          params.each do |key, val|
            parse_err(strict, errors, "illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val != "language-tag"
          end
        when :REV
          params.each do |key, val|
            parse_err(strict, errors, "illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val != "timestamp"
          end
        when :KIND, :XML, :FN, :N, :NICKNAME, :GENDER, :ADR, :EMAIL, :TITLE, :ROLE, :ORG,
          :CATEGORIES, :NOTE, :PRODID, :VERSION
          params.each do |key, val|
            parse_err(strict, errors, "illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val != "text"
          end
        when :BDAY, :ANNIVERSARY, :DEATHDATE
          params.each do |key, val|
            parse_err(strict, errors, "illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val != "date-and-or-time" && val != "text"
          end
        when :TEL, :RELATED, :UID, :KEY, :BIRTHPLACE, :DEATHPLACE
          params.each do |key, val|
            parse_err(strict, errors, "illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val != "uri" && val != "text"
          end
        when :TZ
          params.each do |key, val|
            parse_err(strict, errors, "illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val != "uri" && val != "text" && val != "utc-offset"
          end
        when :EXPERTISE
          if params && params[:LEVEL]
            parse_err(strict, errors, "illegal value #{params[:LEVEL]} given for parameter :LEVEL of #{prop}", ctx) unless params[:LEVEL] =~ /^(beginner|average|expert)$/i
          end
        when :HOBBY, :INTEREST
          if params && params[:LEVEL]
            parse_err(strict, errors, "illegal value #{params[:LEVEL]} given for parameter :LEVEL of #{prop}", ctx) unless params[:LEVEL] =~ /^(high|medium|low)$/i
          end
        end
        errors
      end

      private

      def parse_err(strict, errors, msg, ctx)
        if strict
          raise ctx.report_error msg, "source"
        else
          errors << ctx.report_error(msg, "source")
        end
      end
    end
  end
end