2009-12-31 5 views
4

사용자가 정규 표현식을 기반으로 데이터를 일치시킬 수있는 함수를 작성하려고하지만 사용자 문자열의 위생에 우려하고 있습니다. SQL 쿼리를 사용하면 SQL 삽입 공격을 피하기 위해 바인드 변수를 사용할 수 있지만 정규식에 대한 메커니즘이 있는지 확실하지 않습니다. Regexp.escape이 있지만 유효한 정규 표현식을 허용하고 싶습니다. 난 그냥 tag.name에 직접 일치하고 있기 때문에사용자 정규화 살생

def tagged?(text) 
    tags.each do |tag| 
     return true if text =~ /#{tag.name}/i 
    end 
    return false 
    end 

누군가가 정규 표현식의 탈옥과 혼란을 야기 할 수있는 PROC 호출 또는 무언가를 삽입 할 수있는 기회가 :

다음은 샘플 기능입니다?

모범 사례에 대한 조언을 주시면 감사하겠습니다.

답변

5

보간 문자열은 실행되지 않습니다,하지만 성가신 경고를 생성 않습니다

/#{exit -3}/.match('test') 
# => exits 

foo = '#{exit -3}' 
/#{foo}/.match('test') 
# => warning: regexp has invalid interval 
# => warning: regexp has `}' without escape 

두 개의 경고는 각각 오프닝 # {와 닫는}에 관련된 것, 그리고 독립적이다.

보다 효율적인 전략으로 태그 목록을 한 번 실행할 수있는 결합 된 정규 표현식으로 위생 처리 할 수 ​​있습니다. 일반적으로 N 개의 정규 표현식을 사용하여 N 개의 정규 표현식을 구성하고 테스트하는 것이 훨씬 효율적입니다.

아마도이의 라인을 따라 뭔가 :

class Taggable 
    def tags 
    @tags 
    end 

    def tags=(value) 
    @tags = value 

    @tag_regexp = Regexp.new(
     [ 
     '^(?:', 
     @tags.collect do |tag| 
      '(?:' + tag.sub(/\#\{/, '\\#\\{').sub(/([^\\])\}/, '\1\\}') + ')' 
     end.join('|'), 
     ')$' 
     ].to_s, 
     Regexp::IGNORECASE 
    ) 
    end 

    def tagged?(text) 
    !!text.match(@tag_regexp) 
    end 
end 

이이처럼 사용할 수 있습니다 : 출구 호출이 실행 된

e = Taggable.new 
e.tags = %w[ #{exit-3} .*\.gif .*\.png .*\.jpe?g ] 

puts e.tagged?('foo.gif').inspect 

경우, 프로그램이 중단 것이나, 그것은 단지 해석 그것은 리터럴 문자열입니다. 경고를 피하기 위해 백 슬래시로 이스케이프 처리됩니다.

+0

나는 proc를 삽입하려고 시도하면서 동일한 오류가 발생했다. activerecord 객체에 할당 될 때 이스케이프 처리되는 것 같습니다 : # 그리고 내가 실제로 사용하려고 할 때와 같은 오류가 발생합니다. 정규식. 내가 누락 된 것이 있는지 확실하지 않았습니다. –

1

대신 Regexp 클래스의 인스턴스를 만들어야합니다. regexp와의

def tagged?(text) 
    return tags.any? { |tag| text =~ Regexp.new(tag.name, Regexp::IGNORECASE) } 
end