Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:lun10_plsql_find_cc_in_text

In Textfeldern mit PL/SQL nach Kreditkarten Nummer mit Hilfe des Lun10 suchen

In einer PCI konformen Umgebung dürfen keine Kreditkarten Nummer „versteckt“ in Bemerkungsfeldern hinterlegt werden.

Um die Bemerkungsfelder zu testen, überprüft die folgende PL/SQL Prozedur „analyseCCText“ ob in dem Text eine Kreditkarten Nummer versteckt haben könnte.

Dazu werden alle Buchstaben aus dem Text entfernt und dann die entstandenen Zahlenfolgen Stelle für Stelle auf eine mögliche Kreditkarte untersucht.

Mit dem Luhn10 Algorithmus für Prüfung auf eine gültige Kreditkarten Sequenz wird die Zahlenfolge einer Kreditkarte auch dann erkannt, wenn der Mitarbeiter diese mit diversen „Tricks“ möglichst unkenntlich gemacht hat.

PL/SQL Umsetzung über ein Package

Spezifikation:

search_CC.pks
CREATE OR REPLACE package search_CC
AS
   TYPE num_arry IS TABLE OF NUMBER
                       INDEX BY binary_integer;
 
   FUNCTION showCreditCardType (p_number varchar2)
      RETURN varchar2;
 
   /*
   check if the number string can be check with the LuhnMod10 alogrithmus
       1  Sucess - is a Luh10 Number
      -1  Invalid
   */
   FUNCTION checkLuhnMod10 (p_number NUMBER)
      RETURN INTEGER;
 
   /*
    Read textstring and search for valid creditcards
 
   */
   FUNCTION analyseCCText (p_text varchar2)
      RETURN varchar2;
END;
/

Body:

search_CC.pkb
CREATE OR REPLACE package body search_CC
AS
   G_DEBUG           constant BOOLEAN := FALSE;
   G_CC_CARD_FOUND   constant varchar2 (20) := 'CC';
 
   g_charreturn      constant varchar2 (2) := '
';
 
 
 
   FUNCTION getCCfromList (p_list     OWA_UTIL.ident_arr
                          ,p_start    pls_integer DEFAULT 1)
      RETURN varchar2
   IS
      v_cc       varchar2 (32000);
      v_return   varchar2 (32000);
      v_result   varchar2 (32000);
   BEGIN
      IF p_start < p_list.COUNT
      THEN
         --- Count of tockens
         FOR i IN p_start .. p_list.COUNT
         loop
            DBMS_OUTPUT.put_line (
                  'GPI Tools : getCCfromList => get  tocken ('
               || TO_CHAR (i)
               || ') => '
               || p_list (i));
 
            v_cc := v_cc || p_list (i);
 
            IF LENGTH (v_cc) > 13
            THEN
               DBMS_OUTPUT.put_line (
                  'GPI Tools : analyseCCText =>check String for CC ' || v_cc);
 
               IF G_DEBUG
               THEN
                  v_return :=
                     showCreditCardType (v_cc) || ' for ' || v_cc || '  ';
               ELSE
                  v_result := showCreditCardType (v_cc);
 
                  IF v_result = G_CC_CARD_FOUND
                  THEN
                     v_return := v_result || ' for ' || v_cc || '  ';
                  END IF;
               END IF;
 
               exit;
            END IF;
         END loop;
 
         v_return :=
               v_return
            || ''
            || getCCfromList (p_list => p_list, p_start => p_start + 1);
      ELSE
         RETURN '';
      END IF;
 
      RETURN v_return;
   END getCCfromList;
 
 
 
   /*
    Read textstring and search for valid creditcards
 
   */
 
   FUNCTION analyseCCText (p_text varchar2)
      RETURN varchar2
   IS
      v_textstring   varchar2 (32000) := p_text;
 
      v_token        OWA_UTIL.ident_arr;
      v_tokennum     OWA_UTIL.num_arr;
      v_tokenlen     INTEGER;
      v_count        pls_integer := 1;
      v_return       varchar2 (32000) := 'NOT ANALYSED';
      v_length       INTEGER := 0;
   BEGIN
      -- Remove text from the string
      v_textstring := REPLACE (v_textstring, g_charreturn, ' ');
      v_textstring :=
         TRANSLATE (UPPER (v_textstring)
                   ,'ABCDEFGHIJKLMNOPQRSTUVWÄÜÖXYZÀÌ'
                   ,'X');
      v_textstring := REPLACE (v_textstring, 'X', '');
      DBMS_OUTPUT.put_line (
         'GPI Tools : analyseCCText => normalized string 1 ' || v_textstring);
      -- remove spezieal signs
      v_textstring :=
         TRANSLATE (v_textstring
                   ,'²³{[]}\~|!"§$%&/()=?`*''#+´ß@€^°<>„“…¿'
                   ,'X');
      v_textstring := REPLACE (v_textstring, 'X', '');
      DBMS_OUTPUT.put_line (
         'GPI Tools : analyseCCText => normalized string  2 ' || v_textstring);
 
      -- use this to seperate numbers strings
      v_textstring := REPLACE (v_textstring, '.', ',');
      v_textstring := REPLACE (v_textstring, '-', ',');
      v_textstring := REPLACE (v_textstring, ':', ',');
      v_textstring := REPLACE (v_textstring, '_', ',');
      v_textstring := REPLACE (v_textstring, ';', ',');
 
      DBMS_OUTPUT.put_line (
         'GPI Tools : analyseCCText => normalized string 3 ' || v_textstring);
 
      v_textstring := RTRIM (LTRIM (v_textstring));
 
      -- three times space
      v_textstring := REPLACE (v_textstring, '   ', ' ');
      -- two times space
      v_textstring := REPLACE (v_textstring, '  ', ' ');
      -- use , as sperator
      v_textstring := REPLACE (v_textstring, ' ', ',');
      v_textstring := REPLACE (v_textstring, ',,,,,', ',');
      v_textstring := REPLACE (v_textstring, ',,,', ',');
      v_textstring := REPLACE (v_textstring, ',,', ',');
 
      v_textstring := RTRIM (LTRIM (v_textstring, ','), ',');
      -- if only on number exists
      v_textstring := v_textstring || ',';
 
      DBMS_OUTPUT.put_line (
         'GPI Tools : analyseCCText => normalized string 4 ' || v_textstring);
 
      -- tokeniser all elements or the text, Sperator ' '
      OWA_UTIL.comma_to_ident_arr (v_textstring
                                  ,v_token
                                  ,v_tokennum
                                  ,v_tokenlen);
 
      -- generate a moving window to collect the strings together
      v_return := getCCfromList (p_list => v_token, p_start => 1);
      RETURN v_return;
   exception
      WHEN others
      THEN
         RETURN v_textstring;
   END analyseCCText;
 
 
 
   /*
        identify a number as a creditcard number
 
        Returns the type of a creditcard number
        check if the number is a valid  (Luhn Number check)
        Returns: The type of Creditcard or NONE if not valid
        */
 
   FUNCTION showCreditCardType (p_number varchar2)
      RETURN varchar2
   IS
      v_cardnumber   NUMBER;
      v_cardstring   varchar2 (200);
      v_cardtype     varchar2 (200) := 'UNKOWN';
      v_return       varchar2 (200) := 'UNKOWN';
 
      v_lenght       pls_integer;
 
      v_d1           pls_integer;
      v_d2           pls_integer;
      v_d3           pls_integer;
      v_d4           pls_integer;
   BEGIN
      -- normalize number
      v_cardstring := RTRIM (LTRIM (p_number));
      v_cardstring :=
         TRANSLATE (
            UPPER (v_cardstring)
           ,'.-,;:_#*+@ABCDEFGHIJKLMNOPQRSTUVW!"§$%&/()=²³{[]}?ßÄÜÖ'
           ,'X');
      v_cardstring := REPLACE (v_cardstring, 'X', '');
 
      -- check on valid number
      BEGIN
         v_cardnumber := TO_NUMBER (v_cardstring);
      exception
         WHEN VALUE_ERROR
         THEN
            RETURN 'VALUE ERROR';
      END;
 
      --check length
      v_lenght := LENGTH (v_cardstring);
 
      IF v_lenght BETWEEN 13 AND 16
      THEN
         v_d1 := TO_NUMBER (SUBSTR (v_cardstring, 1, 1));
         v_d2 := TO_NUMBER (SUBSTR (v_cardstring, 1, 2));
         v_d3 := TO_NUMBER (SUBSTR (v_cardstring, 1, 3));
         v_d4 := TO_NUMBER (SUBSTR (v_cardstring, 1, 4));
 
         --- 13
         IF v_lenght = 13
         THEN
            IF v_d1 IN (4)
            THEN
               v_cardtype := 'VISA';
            END IF;
         END IF;
 
         --14
         IF v_lenght = 14
         THEN
            IF v_d2 IN (36, 38)
            THEN
               v_cardtype := 'DINERS CLUB';
            elsif v_d3 IN (300, 301, 302, 303, 304, 305)
            THEN
               v_cardtype := 'DINERS CLUB';
            END IF;
         END IF;
 
         --15
         IF v_lenght = 15
         THEN
            IF v_d2 IN (34, 37)
            THEN
               v_cardtype := 'AMEX';
            elsif v_d4 IN (2014, 2149)
            THEN
               v_cardtype := 'enROUTE';
            elsif v_d4 IN (2131, 1800)
            THEN
               v_cardtype := 'JBC';
            END IF;
         END IF;
 
         --16
         IF v_lenght = 16
         THEN
            IF v_d1 IN (4)
            THEN
               v_cardtype := 'VISA';
            elsif v_d1 IN (3)
            THEN
               v_cardtype := 'JBC';
            elsif v_d2 IN (51, 52, 53, 54, 55)
            THEN
               v_cardtype := 'MASTERCARD';
            elsif v_d4 IN (6011)
            THEN
               v_cardtype := 'DISCOVER';
            END IF;
         END IF;
 
 
         -- Check on Lun CC
         DBMS_OUTPUT.put_line (
               'GPI Tools : showCreditCardType => test  num '
            || TO_CHAR (v_cardnumber)
            || ' and type '
            || v_cardtype);
 
         IF checkLuhnMod10 (v_cardnumber) = 0
         THEN
            IF G_DEBUG
            THEN
               v_return := 'VALID CC NUM TYPE ' || v_cardtype;
            ELSE
               IF v_cardtype != 'UNKOWN'
               THEN
                  v_return := G_CC_CARD_FOUND;
               ELSE
                  v_return := 'NO CC';
               END IF;
            END IF;
         ELSE
            IF G_DEBUG
            THEN
               v_return := 'CC NUM Error TYPE ' || v_cardtype;
            ELSE
               v_return := '-';
            END IF;
         END IF;
      ELSE
         v_cardtype := 'NO CC NUM';
      END IF;
 
      RETURN v_return;
   END showCreditCardType;
 
   /*
      create arry from a number
 
      */
 
   FUNCTION getNumArray (p_number NUMBER)
      RETURN num_arry
   IS
      v_numstring   varchar2 (32) := TO_CHAR (p_number);
      v_nums        num_arry;
      v_pos         pls_integer;
   BEGIN
      FOR i IN 1 .. LENGTH (v_numstring)
      loop
         v_nums (i) := TO_NUMBER (SUBSTR (v_numstring, i, 1));
         DBMS_OUTPUT.put_line (
            'GPI Tools : getNumArray => get  num ' || TO_CHAR (v_nums (i)));
      END loop;
 
      RETURN v_nums;
   END;
 
   /*
         check if the number string can be check with the LuhnMod10 alogrithmus
             1  Sucess - is a Luh10 Number
            -1  Invalid
      */
 
   FUNCTION checkLuhnMod10 (p_number NUMBER)
      RETURN INTEGER
   IS
      v_nums     num_arry;
      v_pos      pls_integer := 1;
      v_return   INTEGER := 0;
      v_total    num_arry;
   BEGIN
      -- create number array from a number
      v_nums := getNumArray (p_number);
 
      FOR i IN reverse 1 .. v_nums.COUNT
      loop
         IF MOD (v_pos, 2) = 0
         THEN
            v_total (i) := (v_nums (i) * 2);
         ELSE
            v_total (i) := (v_nums (i));
         END IF;
 
         v_pos := v_pos + 1;
      END loop;
 
      FOR i IN 1 .. v_total.COUNT
      loop
         IF v_total (i) > 9
         THEN
            v_nums := getNumArray (v_total (i));
 
            FOR x IN 1 .. v_nums.COUNT
            loop
               v_return := v_return + v_nums (x);
            END loop;
         ELSE
            v_return := v_return + v_total (i);
         END IF;
      END loop;
 
      RETURN MOD (v_return, 10);
   END;
END;
/

Verwendung

-- Debug Messages ausgeben ( falls im Code freigeschaltet! )
sql>SET serveroutput ON
 
- Text analysieren
 
sql>SELECT id, search_cc.analyseCCText(bemerkung) AS RESULT 
      FROM bemerkungstexte 
     WHERE cdatum < sysdate -10
    / 
 
 
id  | RESULT
---------------------------
100   VALID CC NUM TYPE VISA 45*******

Quellen

Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
"Autor: Gunther Pipperr"
prog/lun10_plsql_find_cc_in_text.txt · Zuletzt geändert: 2013/07/11 21:57 von Gunther Pippèrr