SAPMSYST登录程序_2015年版本

program sapmsyst message-id 00.
*07.12.1993
*19.04.1996 Dynpro D0025 (Anmeldung per ext. Programm GUI-API)
*05.05.1997 Copyrightcheck & -textbeschaffung ausgelagert
*13.06.1997 Copyrightcheck in Formroutinen                      (PDW)
*18.06.1997 Anmeldung in SPA US2 speichern fuer Status-Popup
*29.09.1997 Korrektur (Copyright kam immer in System-Default-Sprache)
*21.01.1998 Parameter SPR wird nicht mehr immer gesetzt!
*18.02.1998 Anmeldung mit SNC mit Listauswahl                    (FB)
*25.03.1998 Mehrfachanmeldung verhindern                        (PDW)
*13.11.1998 Logo/HTML auf Anmeldebild                            (FB)
*10.02.1999 Dynpro 500 (Lizenzinfo bei Mehrfachanmeldung)        (WJ)
*24.02.1999 Profileparameter 'login/disable_multi_gui_login' (neu)
*           und 'login/multi_login_users' (modifiziert)          (WJ)
*02.03.1999 TEXTPOOL: LOOP ==> READ TABLE                        (FB)
*10.03.1999 Logo/HTML auf Anmeldebild deaktiviert                (FB)
*10.03.1999 Login Screen Info                                    (FB)
*01.04.1999 Kennwort?nderung per RFC überarbeitet                (FB)
*12.05.1999 Mehrfachanmeldeprüfung in den Kernel vorverlegt      (WJ)
*26.05.1999 Dynpro 500: OK-Code ==> RSYST-PF25, "CANC"           (WJ)
*01.09.1999 LIST_COPYRIGHT: TIME=RSYST-TX22                      (WJ)
*24.11.1999 Dynpro 500: MULTI_LOGON_CHECK_CALLED eingefuehrt     (WJ)
*30.11.1999 SNC falsche Meldung "Kein Benutzer vorhanden..."     (FB)
*07.08.2000 Aufruf von SUBST_INS_STAT entfernt, da obsolet       (WJ)
*02.10.2001 MODULE D029_USER_EXIT                                (WJ)
*30.10.2001 Dynpro 0042 (und 'login/password_change_for_SSO')    (WJ)
*20.11.2001 Dynpro 0500 (HANDLE_MULTI_LOGON_DISABLED: Fehler)    (WJ)
*26.11.2001 Dynpro 0043 (bzw. Transaktion PASSWORD) angelegt     (WJ)
*29.01.2003 Unused forms of SUSR_LOGIN_CHECK_RFC deleted         (FB)
*29.01.2003 Calls of DOCU_INIT/DOCU_READ replaced by own code    (FB)
*04.03.2003 multiple logon check improved (check again at PAI)   (WJ)
*04.03.2003 SNC logon with service user => don't raise E message (WJ)
*04.03.2003 SNC selection screen - proper handling for scrolling (WJ)
*02.09.2003 Enable SNC logon despite C_LOCKED_BY_FAILED_LOGON    (WJ)
*07.10.2003 snc/force_login_screen : check on '1' instead of 'X' (WJ)
*07.05.2004 SNC logon attempt to locked client (scroll handling) (WJ)
*03.11.2004 password change dialogs: support long passwords      (WJ)
*13.01.2005 SUSR_PASSWORD_CHANGE_DIALOG: enable to abort dynpro  (WJ)
*19.04.2006 MODULE STATUS_0043: modify screen     (note 942001)  (WJ)
*01.10.2007 Extension of login/multi_login_users  (note 1098186) (UB)
*12.12.2007 Enhanced error handling for SU3 password changing    (WJ)
*22.02.2008 Compare new passwords not case-sensitive if
*           login/password_downwards_compatibility is set to 5   (UB)
*17.01.2011 PAI module RFCAUTH calling new kernel function (ANDRONACHE)
*17.01.2011 SET PARAMETER 'US2' removed (done by kernel)         (WJ)
*22.02.2011 Enable password logon if no SNC mapping exists       (WJ)
*03.03.2011 Display I-message if (previous) failed logons > 0    (WJ)
*13.01.2015 Handling password_change_for_SSO (note 2112577)      (WJ)

tables: tline, thead, dokil, dsyst.
tables: usr01, usr02, *usr02, ush02, usr03, rsyst, usr22.   "USR0340A
tables: xu180.


* Konstante fuer Benutzertyp
data: typcpic value 'C'.
* Konstanten fuer Datenbank & Copyright jetzt in Forms Copyright_Check..

data: menueflag type i value 0,
      text1(132),
      text2(132),
      text3 like dsyst-doktitle.
data: z type i value 0,
      fcode(4).

data: xcode like usr02-bcode,          "Hilfsfeld fuer codierte Passwort
      xcodvn like usr02-codvn.         "Hilfsfeld fuer Codeversion

field-symbols: <text>.

* Copyright-Text
data: copyright_lines type i.

data: begin of sap_copyright occurs 20.
        include structure tline.
data: end of sap_copyright.

data: begin of db_copyright occurs 20.
        include structure tline.
data: end of db_copyright.

data: begin of head.
        include structure thead.
data: end of head.

data: begin of nrtext occurs 10.
        include structure textpool.
data: end of nrtext.

data: id(2),
      object like dokil-object,
      state  like dokil-dokstate.
data: langu like sy-langu.                                  "BINK104530

data: rfc_program_id like rs38l-include. "RFC-Berechtigungsprüfung
data: rfc_function_id like sy-xform. "RFC-Berechtigungsprüfung
data: rfc_indikator(1) type c value space.  "Indikator


*---------------------------------------------------------------------*
* Felder die benoetigt werden fuer:
*       Dynpro 0025:
*---------------------------------------------------------------------*
data:
        d0025_transaction(132),        "Starttransaktion u. evtl.
                                       "Parameter
        d0025_new_bcode like rsyst-bcode.    "Neues Passwort


*---------------------------------------------------------------------*
* Felder die benoetigt werden fuer:
*       Dynpro 0042 / 0043
*---------------------------------------------------------------------*
constants: session_info type x value 2.
data:      auth_type    type c.
data:      pwdstate     type XUPWDSTATE.
data:      password_change_for_SSO.
data:      password_downwards_comp.
data:      pwd_rc       like sy-subrc.
data:      FCODE_0043   like RSYST-FCODE.
data:      CANCEL_0043(1).
data:      INTROTEXT1(95),
           INTROTEXT3(50),
           ERRORTEXT(95).
data:      policy        type security_policy_name,
           l_sec_context type security_context,
           l_pwd_logon   type abap_bool.


*---------------------------------------------------------------------*
* Felder die benoetigt werden fuer:
*       Dynpro 0200:
*---------------------------------------------------------------------*

data:                                  "Funktionscode
        newcode(8),
        newcode1(8),
        newpassflag type p value 0.

data already_shown.

*---------------------------------------------------------------------*
* Felder fuer Lizenzinformation bei Mehrfachanmeldung (Dynpro 500)    *
*---------------------------------------------------------------------*
data: multi_logon_text(250),"User xxx, client xxx is already logged in
      multi_logon_text2(250), "add. info (replacing the table control)
      multi_logon_opt1,  "terminate all other sessions
      multi_logon_opt2,  "open another (parallel) session
      multi_logon_opt3,  "cancel this logon session
      multi_logon_dummy. "used to suppress empty lines when hide option2
controls: multi_logon_tc type tableview using screen 500.
* globale Daten (für PAI-/PBO-Module zu Dynpro 500)
data:  begin of multi_logon_tab occurs 0,
          terminal   like usr41-terminal,
          server     like usr41-server,
          termid     like usr41-termid,  "für CALL 'ThSndDelUser'
          logon_date like usr41-logon_date,
          logon_time like usr41-logon_time,
       end of multi_logon_tab.
data:  multi_logons         type i value 0.  " counter: other logons
data:  multi_logon_disabled type c.          " prof. param. value (0/1)
data:  multi_login_user     type i value 0.  " flag due to prof. param.
data:  multi_logon_check_called type c.

*---------------------------------------------------------------------*
* Felder fuer Anmeldung mit externer ID                               *
*---------------------------------------------------------------------*
data: fatal_error    value ' '.

*---------------------------------------------------------------------*
*       MODULE D020_COPYRIGHT                                         *
*---------------------------------------------------------------------*
* Popup mit Copyright ausgeben, falls noch nicht gezeigt              *
*---------------------------------------------------------------------*
data installations_status like sy-subrc.
*
module d020_copyright.

* Zun?chst Zahl der Anmeldungen prüfen (Dynpro SAPMSYST/0500)
* PERFORM CHECK_MULTI_LOGON.  "wird ab sofort vom Kernel gerufen!

  perform get_copyright_text
                    tables   sap_copyright
                             db_copyright.
  perform copyright_check
                    tables   sap_copyright
                             db_copyright
                    using    rsyst-mandt rsyst-bname
                    changing already_shown.
  if already_shown = ' '.
    call screen 021 starting at 32 1 ending at 77 18.
  else.
    call dialog 'SYSTEMNACHRICHTEN'.  "Dynpro SAPMSEM1/0700
    perform set_spr.
    set screen 040.
  endif.
*
*  07.08.2000 - laut Robert Voelkel ist Aufruf überflüssig
*
*  call function 'SUBST_INS_STAT'
*       importing
*            status = installations_status.
*  if installations_status = 1.
*    message i735.
**   Ihr System ist nicht korrekt installiert
*  endif.
endmodule.


*---------------------------------------------------------------------*
*       MODULE D021_SUPPRESS                                          *
*---------------------------------------------------------------------*
* Popup mit Copyright unterdruecken                                   *
*---------------------------------------------------------------------*
module d021_suppress output.
  set pf-status 'RGHT'.
  set titlebar  'RGH'.
  suppress dialog.
endmodule.


*---------------------------------------------------------------------*
*       MODULE D021_FUNCT                                             *
*---------------------------------------------------------------------*
* Functionscode fuer Popup bei Copyright                              *
*---------------------------------------------------------------------*
module d021_funct.
  if menueflag = 1.
    set screen 040.
  else.
* Feststellen, ob es sich um einen CPIC-Benutzer handelt, dann kein
* Copyrightbild bringen.
    perform set_spr.
    select single * from usr02
           where bname = sy-uname.
    if usr02-ustyp = typcpic.
      set screen 040.
    else.
* Das Copyrightbild anzeigen.
      menueflag = 1.
      leave to list-processing.
      new-page no-title no-heading.
      perform list_copyright.
    endif.
  endif.
endmodule.


*---------------------------------------------------------------------*
*       MODULE LIST_COPYRIGHT                                         *
*---------------------------------------------------------------------*
* Liste mit Copyright ausgeben.                                       *
*---------------------------------------------------------------------*
form list_copyright.
  data: date like sy-datum,
        time like sy-uzeit.
*
  set pf-status 'RGHT'.
  set titlebar  'RGH'.
*
* Da waehrend der Anmeldung die Sprache veraendert werden kann, muss
* ich hier die Meldungstexte sicherheitshalber in der SY-LANGU Sprache
* lesen.
*
  read textpool 'SAPMSYST' into nrtext language sy-langu.
*
  skip.
  summary.
  read table nrtext with key id  = 'I' key = '003'.
  if sy-subrc = 0.
    write: nrtext-entry(25), sy-uname.
  endif.
  date = rsyst-tx21.
  if not date is initial.
*   WRITE:   'Letzte Anmeldung am'(001), DATE.
    read table nrtext with key id  = 'I' key = '001'.
    if sy-subrc = 0.
      write: nrtext-entry(25), date.
    endif.
*   WRITE: / '                 um'(002), TIME.
    read table nrtext with key id  = 'I' key = '002'.
    if sy-subrc = 0.
      time = rsyst-tx22.
      write: nrtext-entry(25), time.
    endif.
  else.
*   WRITE: 'Es erfolgte die erste Anmeldung am System'(004).
    read table nrtext with key id  = 'I' key = '004'.
    if sy-subrc = 0.
      write: nrtext-entry(60).
    endif.
  endif.

  uline.
  skip.
  detail.
*
* SAP-Copyright lesen und ausgeben
*
  call function 'SLIC_GET_LICENCE_DATE'
       importing
            licence_date = date.

* Copyright-Text in richtiger Sprache holen;
* beim Lesen für copyright_check ist sy-langu noch nicht richtig.
  perform get_copyright_text
                    tables   sap_copyright
                             db_copyright.
  describe table sap_copyright lines copyright_lines.
  if copyright_lines > 0.
    loop at sap_copyright.
      if sap_copyright-tdline = space.
        skip.
      else.
        write: / sap_copyright-tdline.
      endif.
    endloop.
    format intensified.
    if date < '99990000'.
      read table nrtext with key id  = 'I' key = '010'.
      if sy-subrc = 0.
        write: nrtext-entry(30), date.
        skip.
      endif.
    else.
      read table nrtext with key id  = 'I' key = '011'.
      if sy-subrc = 0.
        write: nrtext-entry(30).
        skip.
      endif.
    endif.
    format intensified off.
  endif.

  describe table db_copyright lines copyright_lines.
  if copyright_lines > 0.
    loop at db_copyright.
      if db_copyright-tdline = space.
        skip.
      else.
        write: / db_copyright-tdline.
      endif.
    endloop.
  endif.
endform.


at user-command.

************************************************************************
* Login-Lastverteil-Algorithmus aufrufen
* Wirkung: in jedem fünften Login wird der Login-Lastverteil-Algorithmus
* ausgefuehrt und fuehrt dadurch zu einer besseren Verteilung der
* angemeldeten Benutzer auf die Applikationsserver, insbesondere wenn
* sich viele Benutzer innerhalb kurzer Zeit anmelden
* 21.3.1995  Guenter Zachmann
************************************************************************
* submit rsrzllg0 and return.

  case sy-ucomm.
    when 'WEIT'.
      set screen 000.
      leave.
    when 'WEI2'.
      set screen 000.
      leave.
  endcase.

*&---------------------------------------------------------------------*
*&      Module  RFCPBO  OUTPUT
*&---------------------------------------------------------------------*
*       Uebernahme von Default-Werten                                  *
*----------------------------------------------------------------------*
module rfcpbo output.
  if ( rfc_indikator is initial ) and not ( sy-xprog is initial ).
    rfc_program_id = sy-xprog.
    rfc_function_id = sy-xform.
    rfc_indikator = 'X'.
  endif.
endmodule.                             " RFCPBO  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  RFCPAI  INPUT
*&---------------------------------------------------------------------*
*       text                                                           *
*----------------------------------------------------------------------*
module rfcpai input.
  set screen 0.
  leave screen.
endmodule.                             " RFCPAI  INPUT

*&---------------------------------------------------------------------*
*&      Form  ASK_FOR_USERNAME
*&---------------------------------------------------------------------*
*       text                                                           *
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form ask_for_username.
  data: systemtype(10).
*
  call 'C_SAPGPARAM'
       id 'NAME' field 'transport/systemtype'
       id 'VALUE' field systemtype.                              "#EC CI_CCALL
  if systemtype = 'SAP' and sy-uname <> 'SAP*' and sy-uname <> 'DDIC'.
    call function 'SUSR_USER_ADDRESS_READ'
         exporting
              user_name              = sy-uname
         importing
              user_usr03             = usr03
         exceptions
              user_address_not_found = 1
              others                 = 2. "USR0340A

*   select single * from usr03
*          where bname = sy-uname.
    if usr03-name1 = space or usr03-name2 = space.  "USR0340A
      xu180-prevname = usr03-name1.    "USR0340A
      xu180-famname = usr03-name2.     "USR0340A
      xu180-abteilung = usr03-abtlg.   "USR0340A
      call screen 70 starting at 25 10 ending at 79 18.
    endif.
  endif.
endform.                               " ASK_FOR_USERNAME

*&---------------------------------------------------------------------*
*&      Module  D070_SET_STATUS  OUTPUT
*&---------------------------------------------------------------------*
*       text                                                           *
*----------------------------------------------------------------------*
module d070_set_status output.
  set pf-status '0070'.
  set titlebar  '070'.
endmodule.                             " D070_SET_STATUS  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  D070_CONTINUE  INPUT
*&---------------------------------------------------------------------*
*       text                                                           *
*----------------------------------------------------------------------*
module d070_continue input.
  if fcode = 'CONT'.
    if xu180-prevname <> space and xu180-famname <> space.
      usr03-bname = sy-uname. "USR0340A
      usr03-name1 = xu180-prevname. "USR0340A
      usr03-name2 = xu180-famname. "USR0340A
      if xu180-abteilung <> space.
        usr03-abtlg = xu180-abteilung. "USR0340A
      endif.
      modify usr03.  "USR0340A    " nur in SAP - Systemen
*     hier muss ZAV noch eingebunden werden (MS)
    else.
      message e173.
    endif.
  endif.
  set screen 000.
endmodule.                             " D070_CONTINUE  INPUT

*&---------------------------------------------------------------------*
*&      Module  D020_USER_EXIT  INPUT
*&---------------------------------------------------------------------*
*       text                                                           *
*----------------------------------------------------------------------*
module d020_user_exit input.
************************************************************************
* Login-Lastverteil-Algorithmus aufrufen
* Wirkung: in jedem fünften Login wird der Login-Lastverteil-Algorithmus
* ausgefuehrt und fuehrt dadurch zu einer besseren Verteilung der
* angemeldeten Benutzer auf die Applikationsserver, insbesondere wenn
* sich viele Benutzer innerhalb kurzer Zeit anmelden
* 21.3.1995  Guenter Zachmann
************************************************************************
  submit rsrzllg0 and return. "#EC CI_SUBMIT

* Check if there have been (previous) failed password logon attempts
* (if there have, then display an informational message)
  DATA: BEGIN OF last_logon,
          date LIKE sy-datum,
          time LIKE sy-uzeit,
          date_now LIKE sy-datum,
          time_now LIKE sy-uzeit,
          pwdlgndate LIKE usr02-pwdlgndate,
          pwdlocnt(3),
        END OF last_logon,
        pwd_counter TYPE i.
  GET PARAMETER ID 'US2' FIELD last_logon.
  pwd_counter = last_logon-pwdlocnt.
  IF pwd_counter > 0.
* Display number of failed logon attempts only if password logon is possible
    CALL FUNCTION 'SUSR_USER_PASSWORD_STATUS_GET'
      EXCEPTIONS
        password_logon_disabled = 1
        user_has_no_password    = 2
        OTHERS                  = 0.
    IF sy-subrc = 0.
      MESSAGE i788(00) WITH pwd_counter.
    ENDIF.
  ENDIF.

* In SAP-Systemen ggf. den ausfuehrlichen Benutzernamen erfragen
* perform ask_for_username.
* Weitere Benutzer Exits
  call function 'SUSR_LOGON_USER_EXIT'
       exceptions
            others = 1.
* Event. eine Transaktion starten
  clear usr01.
  select single * from usr01
         where bname = sy-uname.
  if usr01-strtt <> space.
    leave to transaction usr01-strtt.
  endif.
endmodule.                             " D020_USER_EXIT  INPUT

************************************************************************
* Dynpro 0025 wird prozessiert, wenn eine Anmeldung per
* externem Programm (z.B. GUI-API) ans SAP-System durchgeführt wird
* 19.4.1996  Christian Jendel
************************************************************************
module d0025_pai input.
************************************************************************
* Login-Lastverteil-Algorithmus aufrufen
* Wirkung: in jedem fünften Login wird der Login-Lastverteil-Algorithmus
* ausgefuehrt und fuehrt dadurch zu einer besseren Verteilung der
* angemeldeten Benutzer auf die Applikationsserver, insbesondere wenn
* sich viele Benutzer innerhalb kurzer Zeit anmelden
* 21.3.1995  Guenter Zachmann
************************************************************************
  submit rsrzllg0 and return. "#EC CI_SUBMIT

* Weitere Benutzer Exits
* call function 'SUSR_LOGON_USER_EXIT'
*      exceptions
*           others  = 1.

  perform d0025_password.
  perform d0025_transaction.
endmodule.


*&---------------------------------------------------------------------*
*&      Module  D029_USER_EXIT  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE D029_USER_EXIT INPUT.
* customer exit (SUSR001, ZXUSRU01)
  call function 'SUSR_LOGON_USER_EXIT'
       exceptions
            others = 1.

ENDMODULE.                 " D029_USER_EXIT  INPUT


*---------------------------------------------------------------------*
*       FORM D0025_PASSWORD                                           *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
form d0025_password.
endform.

*---------------------------------------------------------------------*
*       FORM D0025_TRANSACTION                                        *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
form d0025_transaction.
  data: tcode like sy-tcode.

  tcode = d0025_transaction.
  if tcode <> space.
    leave to transaction tcode.
  else.
    clear usr01.
    select single * from usr01
           where bname = sy-uname.
    if usr01-strtt <> space.
      leave to transaction usr01-strtt.
    endif.
  endif.
endform.
*&---------------------------------------------------------------------*
*&      Module  RFCAUTH  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
data: rfcauth_param(8) value space,
      fugr like rs38l-area value space,
      trace(80) type c,
      text(128) type c,
      rfc_login_complete like sy-debug,
      dialog_user_type   like sy-debug,
      abap_trace_active(1) type c.
*
MODULE rfcauth INPUT.
* program_id = sy-xprog. wird in RFCPBO gesetzt !
  CLEAR: text, abap_trace_active.
*
* Systemcall composes all necessary actions which are required after a
* successful RFC logon: These are an authority check and preparation of
* (ext-) debugging.
* Systemcall 'h' will be obsolotete by this new system call.

  CALL 'RFCControl' ID 'CODE' FIELD '5'
                    ID 'PROGRAM_ID' FIELD rfc_program_id
                    ID 'FUNCTION_ID' FIELD rfc_function_id.                 "#EC CI_CCALL

  if sy-subrc = 0.     " authority check successful
* everthing o.k.

  elseif sy-subrc = 4. " authority check unsuccessful
      CONCATENATE sy-mandt '/' rsyst-bname ' (' rfc_function_id ') ' INTO text.
      MESSAGE a719 WITH text.

  else. " system call not available -> old behavior

* RFC-Authority-Check nur wenn Profileparameter gesetzt
    CALL 'C_SAPGPARAM'
         ID    'NAME'
         FIELD 'auth/rfc_authority_check'
         ID    'VALUE'
         FIELD rfcauth_param.                             "#EC CI_CCALL
* Ruechgabewert
    IF ( rfcauth_param > 0 ).
* OLD: fugr = sy-xprog+4(4).                "Name der Funktionsgruppe
*  message s000(sr) with rfc_program_id. "Progmramname als Trace
      CALL FUNCTION 'FUNCTION_INCLUDE_CONCATENATE'
        CHANGING
          program                  = rfc_program_id
          complete_area            = fugr
        EXCEPTIONS
          not_enough_input         = 1
          no_function_pool         = 2
          delimiter_wrong_position = 3
          OTHERS                   = 4.

      IF sy-subrc <> 0.                  "and sy-subrc <> 2.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.

* Ist Abap-Trace aktiv -> Ausgabe vonb Zusatzinformationen
      CALL 'RFCControl' ID 'CODE' FIELD '2'.              "#EC CI_CCALL
      IF sy-subrc = 2. "Abap-Trace aktiv -> Ausgabe der Zusatzinfo
* LOGIN = Y o.k. and = N error, and dialog_user_type = 'Y' and 'N'
        CALL FUNCTION 'RFC_LOGON_INFO'
          IMPORTING
            rfc_login_complete = rfc_login_complete
            dialog_user_type   = dialog_user_type
          EXCEPTIONS
            OTHERS             = 1.
        abap_trace_active = 'X'.
      ENDIF.

      IF ( ( rfcauth_param = 1 OR rfcauth_param = 2 ) AND
             ( fugr NE 'SRFC' ) ) OR ( rfcauth_param > 2 ).
        AUTHORITY-CHECK OBJECT 'S_RFC'
           ID 'RFC_TYPE' FIELD 'FUGR'
           ID 'RFC_NAME' FIELD fugr
           ID 'ACTVT' FIELD '16'.
        IF sy-subrc NE 0.
          IF abap_trace_active = 'X'.
            CONCATENATE rsyst-bname '(' fugr ',' rfc_program_id ','
            rfc_function_id ',' rfc_login_complete dialog_user_type ')'
                                                             INTO text.
          ELSE.
            CONCATENATE rsyst-bname '(' fugr ')' INTO text
                                                 SEPARATED BY space.
          ENDIF.
*  Keine RFC-Berechtigung für Benutzer &.
*        MESSAGE E719 WITH RSYST-BNAME.
          MESSAGE a719 WITH text.
        ENDIF.

        IF abap_trace_active = 'X'.
          CONCATENATE rsyst-bname '(' fugr ',' rfc_program_id ','
          rfc_function_id ',' rfc_login_complete dialog_user_type ')'
                                                           INTO text.
          MESSAGE s000(sr) WITH text.
        ENDIF.
      ENDIF.

    ENDIF.

*   Aktivierung des HTTP/external Debuggings nach RFC-Anmeldung und
*   RFC-Berechtigungsprüfung
    CALL 'RFCControl' ID 'CODE' FIELD 'h'.                "#EC CI_CCALL
  endif.

ENDMODULE.                             " RFCAUTH  INPUT

*---------------------------------------------------------------------*
*       FORM GET_COPYRIGHT_TEXT                                       *
*---------------------------------------------------------------------*
*       Liefert Copyright-Text in aktueller sy-langu-Sprache          *
*---------------------------------------------------------------------*
*  <--  SAP_COPYRIGHT  STRUCTURE  TLINE                               *
*  <--  DB_COPYRIGHT   STRUCTURE  TLINE                               *
*---------------------------------------------------------------------*
form get_copyright_text
                        tables sap_copyright db_copyright.

  data: db_oracle(3)   value 'ORA',
        db_db6(3)      value 'DB6',
        db_informix(3) value 'INF',
        db_sql_db(3)   value 'SQL',
        db_adabas(3)   value 'ADA',
        db_allbase(3)  value 'ALL',
        db_sybase(3)   value 'SYB',
        db_mssql(3)    value 'MSS',
        db_db4(3)      value 'DB4',
        db_db2(3)      value 'DB2',

        copyright_oracle(20)    value 'COPYRIGHT_ORACLE',
        copyright_db6(20)       value 'COPYRIGHT_DB6',
        copyright_informix(20)  value 'COPYRIGHT_INFORMIX',
        copyright_sql_db(20)    value 'COPYRIGHT_SQL-DB',
        copyright_adabas(20)    value 'COPYRIGHT_ADABAS',
* 03/09 mit Version 7.5 wird SAP DB in MaxDB umbenannt
        copyright_mysql(20)     value 'COPYRIGHT_MYSQL',
        copyright_sybase(20)    value 'COPYRIGHT_SYBASE',
        copyright_allbase(20)   value 'COPYRIGHT_ALLBASE',
        copyright_mssql(20)     value 'COPYRIGHT_MSSQL',
        copyright_db4(20)       value 'COPYRIGHT_DB4',
        copyright_db2(20)       value 'COPYRIGHT_DB2'.

* Ende der Konstantendefinition.

  data: copyright_docu(60).

  data: begin of head.
          include structure thead.
  data: end of head.

  data: text3 like dsyst-doktitle.

  data: state like dokil-dokstate.

* 09/03: version of SAP DB / MaxDB
  data: dbvers(10)   TYPE c.


  call function 'DOCU_GET'
       exporting
            id                = 'TX'
            object            = 'COPYRIGHT_SAP'
            langu             = sy-langu
            typ               = 'E'
       importing
            dokstate          = state
            doktitle          = text3
            head              = head
       tables
            line              = sap_copyright
       exceptions
            ret_code          = 1
            no_docu_on_screen = 2
            no_docu_self_def  = 3
            no_docu_temp      = 4.
  if sy-subrc <> 0.
    clear sap_copyright.
    refresh sap_copyright.
  endif.
*
* Bei neuen DB-Plattformen muss hier die Case-Leiste entsprechend
* verlaengert werden, damit jeweils der richtige Copyrighttext bei
* der Anmeldung erscheint. Wichtig ist auch, dass der entsprechende
* Text als Dokubaustein 'COPYRIGHT_...' vorliegt und oben im Header
* dieses Modulpools die Konstanten DB_... und COPYRIGHT_... gepflegt
* werden.
*
  clear copyright_docu.
  case sy-dbsys(3).
    when db_db6.
      copyright_docu = copyright_db6.
    when db_oracle.
      copyright_docu = copyright_oracle.
    when db_informix.
      copyright_docu = copyright_informix.
    when db_sql_db.
      copyright_docu = copyright_sql_db.
    when db_adabas.
      call 'DB_GET_REL' id 'DBRELEASE' field dbvers.
      if dbvers >= '7.5'.   "#EC NOTEXT
        copyright_docu = copyright_mysql.
      else.
        copyright_docu = copyright_adabas.
      endif.
    when db_sybase.
      copyright_docu = copyright_sybase.
    when db_allbase.
      copyright_docu = copyright_allbase.
    when db_mssql.
      copyright_docu = copyright_mssql.
    when db_db4.
      copyright_docu = copyright_db4.
    when db_db2.                       " BINK107016
      copyright_docu = copyright_db2.  " BINK107016
*     :
*     :
*     :
  endcase.
  if copyright_docu <> space.
    call function 'DOCU_GET'
         exporting
              id       = 'TX'
              object   = copyright_docu
              langu    = sy-langu
              typ      = 'E'
         importing
              dokstate = state
              head     = head
         tables
              line     = db_copyright
         exceptions
              ret_code = 1.
    if sy-subrc <> 0.
      clear db_copyright.
      refresh db_copyright.
    endif.
  endif.

endform.


*---------------------------------------------------------------------*
*       FORM COPYRIGHT_CHECK                                          *
*---------------------------------------------------------------------*
*       Bildet Prüfsumme des SAP- und DB-Copyright-Textes, vergleicht *
*       sie mit der in USR22 hinterlegten und speichert sie ggf. dort *
*---------------------------------------------------------------------*
*  -->  SAP_COPYRIGHT            STRUCTURE  TLINE                     *
*  -->  DB_COPYRIGHT             STRUCTURE  TLINE                     *
*  -->  VALUE(MANDANT)           LIKE  RSYST-MANDT                    *
*  -->  VALUE(USER)              LIKE  RSYST-BNAME                    *
*  <--  ALREADY_SHOWN            TYPE  C                              *
*---------------------------------------------------------------------*
form copyright_check
                     tables sap_copyright db_copyright
                     using value(mandant) value(user)
                     changing already_shown.

  data: checksum type i.

  translate user to upper case.
  already_shown = ' '.                 " Default: Copyright zeigen!

  checksum = 0.                 " erster Aufruf, daher auf 0 setzen
  perform copyright_checksum tables sap_copyright
                             changing checksum.
  perform copyright_checksum tables db_copyright
                             changing checksum.

  if checksum > 0.           " Zumindest ein DOCU_GET war erfolgreich
*   Letzte Copyright-Checksumme aus USR22 holen.
    select single * from  usr22
           where  bname = user.
    if sy-subrc = 0.                   " Eintrag zum User gefunden
      if checksum = usr22-copyrtsum.   " Checksumme wie gehabt
        already_shown = 'X'.           " -> Copyright nicht zeigen!
      else.                            " Checksumme veraendert
        select single for update *     " -> Copyright zeigen!
               from usr22
               where  bname = user.
        usr22-copyrtsum = checksum.
        update usr22.                  " neue Checksumme speichern
      endif.
    else.
      if sy-dbcnt = 0.                 " Noch kein Eintrag zum User
        usr22-mandt     = mandant.     " -> Copyright zeigen!
        usr22-bname     = user.
        usr22-copyrtsum = checksum.
        insert usr22.                  " Checksumme zum User speichern
      endif.
    endif.
  endif.
endform.

*---------------------------------------------------------------------*
*       FORM COPYRIGHT_CHECKSUM                                       *
*---------------------------------------------------------------------*
*       Bildet Checksumme einer internen Text-Tabelle                 *
*---------------------------------------------------------------------*
*  -->  LINES       STRUCTURE  TLINE                                  *
*  <->  CHECKSUM    TYPE I                                            *
*---------------------------------------------------------------------*
form copyright_checksum tables lines structure tline
                        changing checksum.

  types: begin of convtype,
          hex1 type x,
          hex2 type x,
          hex3 type x,
          hex4 type x,
        end of convtype.
  field-symbols <conv> type convtype.
  data: convc(4) type c,
        i type i,
        length type i.

  loop at lines.
    length = strlen( lines-tdline ).
    i = 0.
    do length times.
      convc = lines-tdline+i(1).
      assign convc to <conv> casting.
      add <conv>-hex1 to checksum.
      add <conv>-hex2 to checksum.
      add <conv>-hex3 to checksum.
      add <conv>-hex4 to checksum.
      subtract 96 from checksum.
      add 1        to i.
    enddo.
  endloop.
endform.


*---------------------------------------------------------------------*
*       FORM SET_SPR                                                  *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
form set_spr.
  data: langu like sy-langu.
  langu = space.
  get parameter id 'SPR' field langu.
  if langu = space.
    set parameter id 'SPR' field sy-langu.
  endif.
endform.


*---------------------------------------------------------------------*
*       MODULE SELTX_...                                              *
*---------------------------------------------------------------------*
*                                                                     *
*---------------------------------------------------------------------*
data: ret.
*
module seltx_o0 output.
  call 'C_SAPGPARAM'
     id 'NAME' field 'dynpro/select_tx'
     id 'VALUE' field ret.                                       "#EC CI_CCALL
  if sy-subrc eq 0 and ret eq 'X'.
    set screen '0100'.
    leave screen.
  endif.
endmodule.
*---------------------------------------------------------------------*
*       MODULE SELTX_O1 OUTPUT                                        *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
module seltx_o1 output.
*  submit startmen.
endmodule.
*---------------------------------------------------------------------*
*       MODULE SELTX_O2 OUTPUT                                        *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
module seltx_o2 output.
  submit startmen. "#EC CI_SUBMIT
endmodule.
*---------------------------------------------------------------------*
*       MODULE SELTX_I1                                               *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
module seltx_i1.
*  submit startmen.
endmodule.
*---------------------------------------------------------------------*
*       MODULE SELTX_I2                                               *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
module seltx_i2.
* if sy-ucomm = 'XXSESSION_MANAGER'.
*   call transaction 'SESS'.
* endif.
* submit startmen.
endmodule.



*&---------------------------------------------------------------------*
*&      Module  D020_LOGON_WITH_SNC  OUTPUT
*&---------------------------------------------------------------------*
*       Anmeldung mit SNC                         18.2.98 Frank Buchholz
*----------------------------------------------------------------------*
* Globale Daten
include user_constants.

tables: usracl.
*tables: usr02.

** Tabelle USRACLEXT wird bei Dialoganmeldung nicht berücksichtigt
** Die entsprechenden Programmstellen sind mit ** auskommentiert
** tables: usraclext.
** data with_usraclext value 'X'.

constants: true  value 'X',
           false value space.

controls tc_iusracl type tableview using screen '0020'.
data: tc_iusracl_sel,
      begin of iusracl occurs 0,
        mandt   like usracl-mandt,
        bname   like usracl-bname,
*       snc_sid like usracl-snc_sid,
*       guiflag like usracl-guiflag,
*       hname   like usracl-pname,
*       pname   like usracl-pname,
        client_locked(1),
        user_locked(1),
        user_deactive(1),
        user_nodialog(1),
      end of iusracl.
data: tc_old_top_line like tc_iusracl-top_line value 1,
      tc_has_been_scrolled,
      old_rsyst_mandt like rsyst-mandt.

data: login_type like snc_fields-login_type,
      iusracl_cnt type i,
      snc_active value '-',
      force_login_screen value '-',
      pname_appl like rfcdessecu-pname_appl,
      pname_user like usracl-pname,
      hname like usracl-hname,
      user_input value 'X',
      passwd_required,
      direct_logon.

data: extid_restart_counter type i value 0,
      extid_need_mandt     value ' ',
      extid_need_langu     value ' ',
      extid_need_bname     value ' '.
data: rc type i.

*
module d020_logon_with_snc output.
  CONSTANTS: SET_FLAG_NO_SNC_SSO  TYPE X  VALUE  7.


* SNC-Felder zun?chst ausblenden
  perform deactivate_snc_fields.

* SNC-Daten lesen
  if snc_active = '-'.
    snc_active = false.
    call function 'SNC_GET_MY_INFO'
         importing
              pname_appl     = pname_appl
*             SNC_QOP_MIN    =
*             SNC_QOP_MAX    =
*             snc_qop_use    =
              pname_user     = pname_user
*             PNAME_CPIC     =
*             GUI_CONN_TYPE  =
              login_type     = login_type
              rc             = rc
         exceptions
              internal_error = 1
              snc_not_active = 2
              others         = 3.
    case sy-subrc.
      when 0.
        if rc = 0.
*         SNC aktiv
          snc_active = true.
        else.
          message s766(00).            "Allgemeiner SNC Fehler
          exit.
        endif.
      when 1.
        message s766(00).              "Allgemeiner SNC Fehler
        exit.
      when 2.
*       SNC nicht aktiv
        exit.
      when others.
        message s766(00).              "Allgemeiner SNC Fehler
        exit.
    endcase.
*   login_type = 'SS'.                 "######## TEST ######

*   Profileparameter snc/force_login_screen lesen
    call 'C_SAPGPARAM'
      id 'NAME'  field 'snc/force_login_screen'
      id 'VALUE' field force_login_screen.                       "#EC CI_CCALL
    if sy-subrc = 0.
      case force_login_screen.
        when '0' or '1'. "do nothing
        when 'X'.        "downwards-compatibility
                          force_login_screen = '1'.
        when others.     "set default value
                          force_login_screen = '0'.
      endcase.
    else.
*     assume default value (0) if parameter is not set
      force_login_screen = '0'.
    endif.

  endif.
  case login_type.
    when 'SL'.
      perform snc_login_sl.
    when 'SS'.
      perform snc_login_ss.
  endcase.

endmodule.                             " D020_LOGON_WITH_SNC  OUTPUT

*---------------------------------------------------------------------*
*       FORM SNC_LOGIN_SL                                             *
*       SNC-Anmeldung mit Listauswahl nur für Anmeldeart SL           *
*---------------------------------------------------------------------*
form snc_login_sl .

data: cctemplock like t000-cctemplock.

if tc_has_been_scrolled is initial.
  clear: rsyst-mandt, rsyst-bname.
else.
  clear: tc_has_been_scrolled.
  rsyst-mandt = old_rsyst_mandt.
endif.

**if with_usraclext = true.
*** Eingabefelder ?ffnen wenn *-Eintrag aus USRACLEXT ausgew?hlt wurde
**  if user_input = true or passwd_required = true.
**    perform display_usr_fields.
**    loop at screen.
**      if user_input = true
**        and screen-name = 'RSYST-BNAME'.
**        screen-input     = 1.
**        modify screen.
**      endif.
**      if passwd_required = true
**        and screen-name = 'RSYST-BCODE'.
**        screen-input     = 1.
**        modify screen.
**      endif.
**    endloop.
**  endif.
**endif.                               "WITH_USRACLEXT

* Read data
  if tc_iusracl-lines = 0.

*   Hashwert zum SNC-Namen bestimmen
    call function 'SNC_CONVERT_PNAME_TO_KNAME'
       exporting
            pname          = pname_user
       importing
*           KNAMELEN       =
*           KNAME          =
            hname          = hname
            rc             = rc
       exceptions
            internal_error = 1
            others         = 2.
    if sy-subrc <> 0 or rc <> 0.
      message s766(00).                "Allgemeiner SNC Fehler
    endif.

*   Benutzer zum SNC-Namen (HNAME) lesen (über Index)
    select mandt bname                 "snc_sid guiflag hname pname
      from usracl
      client specified
      into table iusracl
      where  hname = hname
      order by mandt bname.                                      "EC CI_SGLSELECT
*   Nur aktive, nicht gesperrte Dialoguser akzeptieren
    loop at iusracl.
      clear:  iusracl-client_locked, iusracl-user_locked,
              iusracl-user_deactive, iusracl-user_nodialog.

*     Ignore inactive clients
      select single mandt cctemplock from t000 into (iusracl-mandt, cctemplock)
        where mandt = iusracl-mandt.
      if sy-subrc ne 0.
        delete iusracl.
*       Tables are inconsistent: We have USRACL but no T000
        continue.
      endif.

*     Check: client locked? (only DDIC/SAP* can logon)
      if not cctemplock is initial and
         iusracl-bname ne 'SAP*' and iusracl-bname ne 'DDIC'.
        iusracl-client_locked = 'X'.
        modify iusracl.
      endif.

      select single gltgv gltgb ustyp uflag from usr02
        client specified
        into (usr02-gltgv, usr02-gltgb, usr02-ustyp, usr02-uflag)
        where mandt = iusracl-mandt
          and bname = iusracl-bname
          and zbvmaster = space.
      if   sy-subrc    ne 0.
        delete iusracl.
*       Tables are inconsistent: We have USRACL but no USR02
*       Use checkprogram RSSNCCHK to repair.
        continue.
      endif.
      data usr02flag type x.
      usr02flag = usr02-uflag.
      if   usr02flag o  c_locked_by_admin
        or usr02flag o  c_locked_by_global_admin.
*       Notice: SNC logon despite C_LOCKED_BY_FAILED_LOGON
*               should be granted (see note 498889)!
        iusracl-user_locked = 'X'.
        modify iusracl.
      endif.
      if   ( not usr02-gltgv is initial and usr02-gltgv >  sy-datum )
        or ( not usr02-gltgb is initial and usr02-gltgb <  sy-datum ).
        iusracl-user_deactive = 'X'.
        modify iusracl.
      endif.
      if usr02-ustyp ne c_usertype_dialog AND
         usr02-ustyp ne c_usertype_service.
        iusracl-user_nodialog = 'X'.
        modify iusracl.
      endif.
    endloop.

*   Anzahl aktive User in USRACL
    describe table iusracl lines iusracl_cnt.

**  if with_usraclext = true.
***   USRACLEXT lesen und in Auswahlliste eintragen
**    data: begin of iusraclext occurs 0,
**            mandt     like usraclext-mandt,
**            bname     like usraclext-bname,
***           snc_sid   like usraclext-snc_sid,
***           hname     like usraclext-hname,
***           pname     like usraclext-pname,
**          end of iusraclext.
**    clear: user_input, passwd_required.
**    select mandt bname "snc_sid hname pname
**      from usraclext
**      client specified
**      into table iusraclext
**      where hname = hname.
**    select mandt bname snc_sid hname pname from usraclext
**      client specified
**      appending table iusraclext
**      where hname = '*'.
**    loop at iusraclext.
**      if iusraclext-bname ne '*'.
**        clear: IUSRACL.
***       Nur aktive, nicht gesperrte Dialoguser akzeptieren
**        select single gltgv gltgb ustyp uflag from usr02
**          client specified
**          into (usr02-gltgv, usr02-gltgb, usr02-ustyp, usr02-uflag)
**          where mandt = iusraclext-mandt
**            and bname = iusraclext-bname.
**        IF   SY-SUBRC    NE 0
**          continue.
**        endif.
**        if   USR02-UFLAG O  C_LOCKED_BY_ADMIN
**          OR USR02-UFLAG O  C_LOCKED_BY_FAILED_LOGON.
**          iusracl-locked = 'X'.
**        endif.
**        if  ( NOT USR02-GLTGV IS INITIAL AND USR02-GLTGV >  SY-DATUM )
**        OR ( NOT USR02-GLTGB IS INITIAL AND USR02-GLTGB <  SY-DATUM ).
**          iusracl-deactive = 'X'.
**        endif.
**        if USR02-USTYP NE C_USERTYPE_DIALOG.
**          continue.
**        endif.
**      endif.
***     Benutzer in Auswahlliste eintragen
**      read table iusracl
**      with key mandt = iusraclext-mandt
**               bname = iusraclext-bname
**      binary search
**      TRANSPORTING NO FIELDS.
**      check sy-subrc ne 0.
**      move-corresponding iusraclext to iusracl.
**      insert iusracl index sy-tabix.
**    endloop.
**  endif.                             "WITH_USRACLEXT

  endif.                               "if tc_iusracl-lines = 0.

* Anmeldung zugelassen?
  describe table iusracl lines tc_iusracl-lines.
  if tc_iusracl-lines = 0.
*   No SNC logon possible -> fallback to password logon
    login_type = 'SD'.
    CALL 'LOGIN_INFO' ID 'OPCODE' FIELD SET_FLAG_NO_SNC_SSO.
*   Kein Benutzer vorhanden mit SNC Name "&"
    MESSAGE s768(00) DISPLAY LIKE 'W' WITH pname_user.
    PERFORM restart_dynpro.
  endif.
  read table iusracl index 1.
  if iusracl_cnt = 1 and tc_iusracl-lines = 1
    and iusracl-client_locked is initial
    and iusracl-user_locked   is initial
    and iusracl-user_deactive is initial
    and iusracl-user_nodialog is initial.

*   Direkte Anmeldung
    direct_logon = true.
    read table iusracl index 1.
    rsyst-mandt = iusracl-mandt.
    rsyst-bname = iusracl-bname.
*   SNC-Anmeldung von &1 &2 für &3
    message s009(snc) with rsyst-mandt rsyst-bname pname_user.
    if force_login_screen = '1'.
      perform display_sncuser_fields.
    else.
      perform activate_snc_fields.
      suppress dialog.
      exit.
    endif.

  else.
*   Auswahl
    user_input = true.
    perform activate_snc_fields.
    message s008(snc). "Bitte R/3-Benutzer eingeben oder ausw?hlen
    exit.
  endif.

endform.                               "snc_login_sl

*---------------------------------------------------------------------*
*       FORM SNC_LOGIN_SS                                             *
*       SNC-Anmeldung Server (login_type='SS')                        *
*                                                                     *
*       Vor erster Dynproausgabe: Keine Mussfelder  im Servermode     *
*       Bei Dynprorestart: Eingabefelder nach Wunsch                  *
*---------------------------------------------------------------------*
form snc_login_ss .
  if extid_restart_counter = 0.
* Keine Musseingaben im ServerMode
    loop at screen.
      if screen-group1 = 'USR' and screen-group2 ne 'SPR'.
        screen-active    = 1.
        screen-input     = 1.
        screen-output    = 1.
        screen-required  = 0.
        modify screen.
      endif.
    endloop.
  else.                                "extid_restart_counter ist > 0
*   Dynprorestart bei Bearbeitung externer ID, weil nur
*   ganz bestimmte Eingabefelder angezeigt werden sollen
*   Bei fatal_error : AGate will Dynpro ohne Eingabefelder !
    loop at screen.
      if fatal_error = true.
        screen-active    = 0.
      else.
        check screen-group1 = 'USR'.
        if screen-name = 'RSYST-BNAME' and extid_need_bname = true
        or screen-name = 'RSYST-MANDT' and extid_need_mandt = true
        or screen-name = 'RSYST-LANGU' and extid_need_langu = true.
          screen-active    = 1.
          screen-input     = 1.
          screen-output    = 1.
          screen-required  = 0.
        else.
          screen-active    = 0.
        endif.
      endif.                           " fatal_error = true
      modify screen.
    endloop.
  endif.                               "extid_restart_processing = 0
endform.                               "snc_login_ss

*---------------------------------------------------------------------*
*       FORM ACTIVATE_SNC_FIELDS                                      *
*---------------------------------------------------------------------*
form activate_snc_fields.
  set pf-status '0020' excluding 'RESE'.
* Benutzerfelder aktivieren
  if user_input = true.
    loop at screen.
      if screen-group1 = 'USR'.
        screen-active    = 1.
        screen-input     = 1.
        screen-output    = 1.
        screen-invisible = 0.
        screen-required  = 0.
        modify screen.
      endif.
    endloop.
  endif.
* Kennwortfelder deaktivieren
  if passwd_required = false.
    loop at screen.
      if screen-group2 = 'PWD'.
        screen-active   = 0.
        screen-required = 0.
        modify screen.
      endif.
    endloop.
  endif.
* SNC-Felder aktivieren
  loop at screen.
    if screen-group1 = 'SNC'.
      screen-active    = 1.
      screen-output    = 1.
      screen-invisible = 0.
      modify screen.
    endif.
  endloop.
  tc_iusracl-invisible = false.
endform.

*---------------------------------------------------------------------*
*       FORM DISPLAY_SNCUSER_FIELDS
*---------------------------------------------------------------------*
form display_sncuser_fields.
  set pf-status '0020' excluding 'RESE'.
* Benutzerfelder aktivieren
* if user_input = true.
  loop at screen.
    if screen-group1 = 'USR' and screen-group2 ne 'SPR'.
      screen-active    = 1.
      screen-input     = 0.
      screen-output    = 1.
      screen-invisible = 0.
      screen-required  = 0.
      modify screen.
    endif.
  endloop.
* endif.
* Kennwortfelder deaktivieren
  if passwd_required = false.
    loop at screen.
      if screen-group2 = 'PWD'.
        screen-active   = 0.
        screen-required = 0.
        modify screen.
      endif.
    endloop.
  endif.
* SNC-Felder aktivieren
  loop at screen.
    if screen-group1 = 'SNC'.
      screen-active    = 1.
      screen-output    = 1.
      screen-invisible = 0.
      modify screen.
    endif.
  endloop.
  tc_iusracl-invisible = true.
endform.

*---------------------------------------------------------------------*
*       FORM DEACTIVATE_SNC_FIELDS
*---------------------------------------------------------------------*
form deactivate_snc_fields.
* SNC-Felder deaktivieren
  loop at screen.
    if screen-group1 = 'SNC'.
      screen-active    = 0.
      modify screen.
    endif.
  endloop.
  tc_iusracl-invisible = true.
endform.

*---------------------------------------------------------------------*
*       FORM RESTART_DYNPRO                                           *
*---------------------------------------------------------------------*
form restart_dynpro.
  if login_type = 'SS'.
    extid_restart_counter = extid_restart_counter + 1.
  endif.
  set screen sy-dynnr.
  leave screen.
endform.

*&---------------------------------------------------------------------*
*&      Module  D020_GET_USER_DATA  OUTPUT
*&---------------------------------------------------------------------*
*       Weitere Benutzerdaten lesen
*----------------------------------------------------------------------*
module d020_get_user_data output.
  check login_type = 'SL'.
  check snc_active = true.
* Erste Zeile der Benutzerauswahlliste markieren
* Deaktiviert da beim Bl?ttern mit markierter Zeile bereits die
* Anmeldung ausgel?st wird.
* if  TC_IUSRACL-CURRENT_LINE = 1.
*   TC_IUSRACL_SEL = 'X'.
* endif.


endmodule.                             " D020_GET_USER_DATA  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  D020_SNC_SELECT_USER  INPUT
*&---------------------------------------------------------------------*
*       Auswahl des R/3-Benutzers
*----------------------------------------------------------------------*
data: cursor_line type i,
      cursor_area(30).
*
module d020_snc_select_user input.
  check login_type = 'SL'.
  check snc_active = true.
  check direct_logon = false.
* Markierspalte ersetzt durch einzelne Drucktasten

  if tc_old_top_line <> tc_iusracl-top_line.
*   table control has been scrolled ...
    tc_old_top_line = tc_iusracl-top_line.
    old_rsyst_mandt = rsyst-mandt.
    tc_has_been_scrolled = 'X'.
    perform restart_dynpro.
  endif.

  get cursor
    line   cursor_line
    area   cursor_area.
  check cursor_area = 'TC_IUSRACL'.

  cursor_line = cursor_line + tc_iusracl-top_line - 1.
  read table iusracl index cursor_line.
  check sy-subrc = 0.
* check TC_IUSRACL_SEL = TRUE.

* Dismiss locked and deactive users
  if iusracl-client_locked = 'X'.
    message e166(00). "Mandant ist gesperrt
  endif.
  if iusracl-user_locked = 'X'.
    message e158(00). "Benutzer ist gesperrt
  endif.
  if iusracl-user_deactive = 'X'.
    message e148(00). "Benutzer ist nicht im Gültigkeitsdatum.
  endif.
  if iusracl-user_nodialog = 'X'.
    message e156(00). "Bitte mit einem Dialogbenutzer anmelden
  endif.

    rsyst-mandt = iusracl-mandt.
    rsyst-bname = iusracl-bname.
    clear: user_input, passwd_required, rsyst-bcode.

**  if with_usraclext = true and
**    ( iusracl-bname = '*' or iusracl-hname = '*' ).
*
**    if rsyst-bname = '*'.
**      clear rsyst-bname.
**      user_input      = true.
**    endif.
**    passwd_required = true.
**    perform restart_dynpro.
*
**  else.                              "WITH_USRACLEXT
*
*     Nochmals Tabelle lesen
    select single mandt bname          "snc_sid guiflag hname pname
      from usracl
      client specified
      into (iusracl-mandt, iusracl-bname)
      where  hname = hname
        and  mandt = rsyst-mandt
        and  bname = rsyst-bname.
    if sy-subrc ne 0.
*       Tabelle ge?ndert Anmeldung nicht mehr m?glich
      clear: tc_iusracl-lines, rsyst-mandt, rsyst-bname.
      perform restart_dynpro.
    endif.

*     Direkte Anmeldung
    direct_logon = true.
*     SNC-Anmeldung von &1 &2 für &3
    message s009(snc) with rsyst-mandt rsyst-bname pname_user.
**  endif.                             "WITH_USRACLEXT


endmodule.                             " D020_SNC_SELECT_USER  INPUT

*&---------------------------------------------------------------------*
*&      Module  D020_SNC_CHECK_SELECTED_USER  INPUT
*&---------------------------------------------------------------------*
module d020_snc_check_selected_user input.
  check login_type = 'SL'.
  check snc_active = true.
  check direct_logon = false.

* Kein Benutzer zugeordnet
  if tc_iusracl-lines = 0.
    clear: rsyst-bname.
*   Kein Benutzer vorhanden mit SNC Name "&"
    message e768(00) with pname_user.
  endif.

* Gültiger R/3-Benutzer eingegeben?
  if not rsyst-mandt is initial and not rsyst-bname is initial.
    read table iusracl
      with key mandt = rsyst-mandt
               bname = rsyst-bname
      transporting no fields.
*   Nochmals Tabelle lesen
    if sy-subrc = 0.
      select single mandt bname        "snc_sid guiflag hname pname
        from usracl
        client specified
        into (iusracl-mandt, iusracl-bname)
        where  hname = hname
          and  mandt = rsyst-mandt
          and  bname = rsyst-bname.
      if sy-subrc ne 0.
*       Tabelle ge?ndert Anmeldung nicht mehr m?glich
        clear tc_iusracl-lines.
      endif.
    endif.
    if sy-subrc ne 0.
      clear: rsyst-bname.              "Krücke, da das Mandantenfeld
                                       "sowieso zurückgesetzt wird.
                                       "E-Message geht nicht, da Table
                                       "Control nicht aktiviert wird.
    endif.
  endif.
* R/3-Benutzer eingegeben?
  if user_input = true and rsyst-bname is initial.
    message s008(snc). "Bitte gült. R/3-Benutzer eingeben oder ausw?hlen
  endif.
* Kennwort erforderlich?
  if passwd_required = true and rsyst-bcode is initial.
    message s010(snc).                 "Bitte Kennwort eingeben
  endif.
* Dynpro erneut anzeigen, wenn kein R/3-Benutzer ausgew?hlt
  if rsyst-mandt is initial or rsyst-bname is initial.
    perform restart_dynpro.
  endif.
endmodule.                 " D020_SNC_CHECK_SELECTED_USER  INPUT

*&---------------------------------------------------------------------*
*&      Module  D020_SNC_CHECK_EXTID  INPUT
*&---------------------------------------------------------------------*
*       Bearbeitung Login mit externer Info:
*       - RFC, um externe Info zu holen
*       - Abbildung auf R/3 User
*       Falls Eingabedaten fehlen, erneutes senden des Anmeldedynpros
*       (nur fehlende Felder offen -> geht nur ueber "Restart")
*----------------------------------------------------------------------*
* Valid values for extid_type :
constants: certificate_base64      type i   value 1,
           max_cert_base64_length  type i   value 8400 .

data: extid_length   like extid_info-length
    , extid_type     like extid_info-type
    .
data: extid_data_table type extid_tab .

data: msg_text(80) type c.             "Message text

data: extid_bname like rsyst-bname     "bname aus der Abbildung
    , extid_dname(1024) type c         "not: like usrextid-extid
    .

*---------------------------------------------------------------------*
*       MODULE D020_SNC_CHECK_EXTID INPUT                             *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
data: extid_data_string  like extid_strg.   "type x
*
module d020_snc_check_extid input.
  check login_type = 'SS' .

  case rsyst-fcode.
    when 'EXTD'.
      if fatal_error = true .
        call 'SYST_LOGOFF'.                                      "#EC CI_CCALL
      endif.
*     Verarbeitung mit externer Id gewuenscht.
*     Zuerst: Externe Id (Zertifikat) abholen.
      if extid_restart_counter = 0.
        call function 'SNC_GET_EXTERNAL_ID'  destination  'SAPGUI'
          importing
            extid_length          = extid_length
            extid_type            = extid_type
          tables
            extid_data            = extid_data_table
          exceptions
            no_data_available     = 1
            internal_error        = 2
            communication_failure = 3 message msg_text
            system_failure        = 4 message msg_text
            others                = 5 .
        if sy-subrc <> 0.
          fatal_error = true.
*         message a012(snc) with sy-subrc msg_text .
          perform snc_jcb_msg using 12 sy-subrc msg_text .
        endif.

*       Externe Id formal pruefen
        perform snc_check_extid
          using extid_length extid_type
          changing rc.
        case rc.
          when 1.
            fatal_error = true.
*           message a017(snc) with extid_length .
            perform snc_jcb_msg using 17 extid_length ' '.
          when 2.
            fatal_error = true.
*           message a016(snc) with extid_type .
            perform snc_jcb_msg using 16 extid_type ' '.
        endcase.
      endif .                          "  extid_restart_counter = 0

*     Pruefen: mindestens Mandant muss da sein.
*     message s800(snc) with rsyst-mandt extid_dname.       "### test
*     perform snc_jcb_msg using 12 extid_type rsyst-mandt . "### test
      if rsyst-mandt is initial.
*       perform snc_jcb_msg using 12 extid_type 'MAND-INI'.  " ### test
        if rsyst-bname is initial.
          rsyst-bname = '*' .
        endif.
        extid_need_mandt      = true.
        extid_need_bname      = true.
        extid_need_langu      = true.
        perform restart_dynpro.
      endif.                           " rsyst-mandt is initial.

*     Der abgeholten externen Id einen R/3-User zuordnen.
      extid_bname = rsyst-bname.
      case extid_type.
        when certificate_base64 .
          perform snc_conv_cert_base64
            tables    extid_data_table
            using     extid_length
            changing  extid_data_string .

          perform snc_map_cert_base64_to_user
*           tables   extid_data_table
            using    rsyst-mandt extid_data_string extid_length
            changing extid_bname extid_dname rc .
        when others.                   " Nicht unterstützer Typ
          fatal_error = true.
*          message a014(snc) with extid_type.
          perform snc_jcb_msg using 14 extid_type ' '.
      endcase.                         " extid_type.

      case rc.
        when 0.                        "alles ok, einfach weiterlaufen
        when 1.                        "Extid nicht gefunden
          if rsyst-bname is initial.   "bname war nicht spezifiziert
            fatal_error = true.
            message s800(snc) with rsyst-mandt extid_dname.
            perform restart_dynpro.
          else.                        "bname war spezifiziert
            extid_need_mandt      = true.
            extid_need_bname      = true.
            extid_need_langu      = true.
            message s013(snc) with rsyst-mandt extid_dname rsyst-bname.
            perform restart_dynpro.
          endif.
        when 2.                        "Benutzer nicht eindeutig
          if rsyst-bname is initial.
            rsyst-bname = '*' .
          endif.
          extid_need_bname      = true.
          extid_need_langu      = true.
          perform restart_dynpro.
      endcase.

*     Benutzer Blank nicht zulassen
      if extid_bname is initial.
        message s800(snc) with rsyst-mandt extid_dname.
        perform restart_dynpro.
      endif.

*     wenn Benutzer ok: Anmeldung aufrufen.
      perform snc_login_from_server
        using      rsyst-mandt  extid_bname rsyst-langu  'D'
        changing   rc .

      case rc.
        when 0.                        "Das war ok
        when 3.                        "Keine SNC Verbindung
          call 'LOGIN_FOR_SNC_SERVER'  "Abbruch message
          id  'MSG_NR'      field 21 .                           "#EC CI_CCALL
        when 4.                        "Keine Server Anmeldung
          call 'LOGIN_FOR_SNC_SERVER'  "Abbruch message
          id  'MSG_NR'      field 22 .                           "#EC CI_CCALL
        when 6.      "Server Login nicht per Profil aktiviert
          call 'LOGIN_FOR_SNC_SERVER'  "Abbruch message
          id  'MSG_NR'      field 19 .                           "#EC CI_CCALL
        when others.                   "Das sollte nicht auftreten ..
          perform snc_jcb_msg using 20 rc ' '.
      endcase.
*
*     rsyst-fcode loeschen, sonst fm: Transaktion EXTD unbekannt.
      rsyst-fcode = '        '.

    when others.                       "case rsyst-fcode
*     Musseingaben pruefen.
*     (Bei Server-Anmeldung ohne FCODE=/EXTD )
      if rsyst-mandt is initial
      or rsyst-bname is initial
      or rsyst-bcode is initial.
        message e055.
      endif.
  endcase.

endmodule.                             " D020_SNC_CHECK_EXTID  INPUT

*---------------------------------------------------------------------*
* Formroutinen zur Prüfung Zertifikat und Ablegen in Memory
* (benutzt durch SAPMSYST selber und FB .... )
* bleibt in SAPMSYST, da dieses Programm 'unsichtbar' ist.
* Karlheinz Kistner  08.05.98
*---------------------------------------------------------------------*
*  -->                                                                *
*  -->                                                                *
*  -->                                                                *
*  <--  RC    = 0 OK                                                  *
*             = 1 extid_type ungueltig                                *
*             = 2 extid_length zu gross                               *
*---------------------------------------------------------------------*
form snc_check_extid
  using    extid_length like extid_info-length
           extid_type   like extid_info-type
  changing rc           like sy-subrc .

  rc = 0.

  case extid_type.
    when certificate_base64   .
      if    extid_length > max_cert_base64_length
         or extid_length < 1  .
        rc = 1.
      endif.
    when others .                      "Invalid type
      rc = 2 .
  endcase.
endform.

*---------------------------------------------------------------------*
* Formroutine zur Dekodierung base64-codiertes Zertifikat auf R/3-User
* (benutzt durch SAPMSYST selber und FB .... )
* bleibt in SAPMSYST, da dieses Programm 'unsichtbar' ist.
* Karlheinz Kistner  08.05.98
*---------------------------------------------------------------------*
form snc_conv_cert_base64
  tables    extid_table              type  extid_tab
  using     extid_length             like  extid_info-length
  changing  extid_data_string        like  extid_strg.

  data: e_line like line of extid_table,
        cum_len     type i  value 0,
        rem_len     type i.
  data: test_msg(100).                 "#### test

  rem_len = extid_length .
*    test_msg = 'Now I am in snc_conv_cert_base6' .      " #### test
*    perform snc_jcb_msg using 12 99  test_msg .         "#### test

  loop at extid_table into e_line.
*    test_msg = e_line .                                 " #### test
*    perform snc_jcb_msg using 12 99  test_msg .         "#### test
    extid_data_string+cum_len(120) = e_line .        "auch ok.
*    test_msg = extid_data_string .                      " #### test
*    perform snc_jcb_msg using 12 99  test_msg .         "#### test
    cum_len = cum_len + 120.
    rem_len = rem_len - 120.
  endloop.
  if rem_len > 0 .
* #### Fehler
  endif.

endform.
*---------------------------------------------------------------------*
*       FORM SNC_MAP_CERT_BASE64_TO_USER                              *
*---------------------------------------------------------------------*
* Formroutine  zur Abbildung base64-codiertes Zertifikat auf R/3-User
* (benutzt durch SAPMSYST selber und FB SNC_LOGIN_EXTERNAL_ID )
* bleibt in SAPMSYST, da dieses Programm 'unsichtbar' ist.
* Karlheinz Kistner  08.05.98
*---------------------------------------------------------------------*
*  -->  mandt                                                         *
*  -->  extid_data_table  Tabelle mit base64-encoded Zertifikat       *
*  -->  bname = blank     externe Id umsetzen, wenn eindeutig         *
*               *         externe Id umsetzen, Default nehmen         *
*               user      prüfen, ob externe Id zu user passt         *
*  <--  bname   gelesener User                                        *
*  <--  dname   Dist. Name aus Zertifikat                             *
*  <--  RC    = 0 OK                                                  *
*             = 1 externe Id nicht gefunden                           *
*             = 2 externe Id nicht eindeutig (bei bname = blank)      *
*---------------------------------------------------------------------*
tables: usrextid.

*---------------------------------------------------------------------*
*       FORM SNC_MAP_CERT_BASE64_TO_USER                              *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  MANDT                                                         *
*  -->  CERT_BASE64                                                   *
*  -->  EXTID_LENGTH                                                  *
*  -->  BNAME                                                         *
*  -->  DNAME                                                         *
*  -->  RC                                                            *
*---------------------------------------------------------------------*
form snc_map_cert_base64_to_user
  using    mandt       like rsyst-mandt
           cert_base64 like extid_data_string
           extid_length like extid_length
  changing bname       like rsyst-bname
           dname       like extid_dname
           rc          like sy-subrc .

  data:    cert_len      type  i,
           dname_len     type  i,
           field_len     type  i.

  data:    issuer(512)   type c,
*          validity(256) type c,
*          snumber(256)  type c,
           issuerh        like usrextid-issuerh,
           stored_issuerh like usrextid-issuerh,
           HASH_OR_DNAME LIKE  USREXTID-EXTID,
           HASH          LIKE  MD5_FIELDS-HASH,
           status        like  usrextid-status.

  constants: get_cert_info  type x   value  101 .
  constants: get_hash       type x   value  3   .

  rc = 0.
  cert_len = extid_length .

* Extract DN from Certificate ----------------------------------------
  call 'SNC_ABAP_INFO'  id 'OPCODE'    field get_cert_info
                        id 'CERT'      field cert_base64
                        id 'CERTLEN'   field cert_len
                        id 'SUBJECT'   field dname
                        id 'ISSUER'    field issuer
*                       id 'SNUMBER'   field snumber
*                       id 'VALIDITY'  field validity
                        .                                        "#EC CI_CCALL
  rc = sy-subrc .
* Irgendein Fehler bei Parsen Zertifikat: Game over
  if rc <> 0.
    perform snc_jcb_msg using 18 rc ' '.
  endif.

* Build Search Key (DN or Hash of DN ) -------------------------------
  describe field usrextid-extid length field_len in character mode.
  dname_len = strlen( dname ).

  if dname_len > field_len.            "Mit Hashwert suchen
*   Extid to long, search with hash
    call function 'MD5_CALCULATE_HASH_FOR_CHAR'
          exporting
               data           = dname
               length         = dname_len
*              VERSION        = 1
          importing
               hash           = hash
          exceptions
               internal_error = 1
               others         = 2.
    if sy-subrc <> 0.
*   #####
    endif.
    hash_or_dname = hash.
  else.
    hash_or_dname = dname.
  endif.
* dname = 'CN=ZertUser, OU=TEST, O=SAP, C=DE'.  " #### Test

  case bname.
    when ' '.
      select bname status issuerh from usrextid
        client specified
        into (bname, status, stored_issuerh)
        where mandt  = mandt
          and type   = 'DN'
          and extid  = hash_or_dname
          and status = 'X'.                                      "EC CI_SGLSELECT
      endselect.
      if sy-subrc <> 0.
        rc = 1.
        exit.
      endif.
      if sy-dbcnt > 1.                 "Mehrere Treffer
        clear bname.
        rc = 2.
        exit.
      endif.
*
    when '*'.
      select single bname status issuerh from usrextid
        client specified
        into (bname, status, stored_issuerh)
        where mandt = mandt
          and type  = 'DN'
          and extid = hash_or_dname
          and seqno = 0
          and status = 'X'.

      if sy-subrc <> 0.
        rc = 1.
        exit.
      endif.
*
    when others.                       "lesen mit Extid und Bname
      select single bname status issuerh from usrextid
        client specified
        into (bname, status, stored_issuerh)
        where mandt = mandt
          and type  = 'DN'
          and extid = hash_or_dname
          and status = 'X'
          and bname = bname .
      if sy-subrc <> 0.
        rc = 1.
        exit.
      endif.
  endcase.
  if status ne 'X'.
    raise USER_INACTIVE.
  elseif not stored_issuerh is initial.
    call function 'MD5_CALCULATE_HASH_FOR_CHAR'
         exporting
              data           = issuer
*             length         =
              version        = 1
         importing
              hash           = issuerh
         exceptions
              internal_error = 1
              others         = 2.
    if sy-subrc ne 0.
        rc = 1.
        exit.
    elseif stored_issuerh ne issuerh.
        rc = 1.
        exit.
    endif.
  ENDIF.

endform.

*---------------------------------------------------------------------*
* Formroutinen zur "Server"-Anmeldung ueber dynpsign
* (benutzt durch SAPMSYST selber und FB SNC_LOGIN_EXTERNAL_ID )
* bleibt in SAPMSYST, da dieses Programm 'unsichtbar' ist.
* Karlheinz Kistner  08.05.98
*---------------------------------------------------------------------*
*  -->  MANDT                                                         *
*  -->  BNAME                                                         *
*  -->  DIA_RFC (D/R, fuer DIAG / RFC )                               *
*  <--  RC    = 0 OK                                                  *
*             = 1 login_type ungueltig                                *
*             = ....                                                  *
*---------------------------------------------------------------------*
form snc_login_from_server
  using    mandt      like rsyst-mandt
           bname      like rsyst-bname
           langu      like rsyst-langu
           dia_rfc    type c
  changing rc         like sy-subrc .

  rc = 0.
  if     dia_rfc <> 'D'
     and dia_rfc <> 'R' .
    rc = 1.
    exit.
  endif.

  call 'LOGIN_FOR_SNC_SERVER'
    id  'MANDT'      field mandt
    id  'BNAME'      field bname
    id  'LANGU'      field langu
    id  'DIA_RFC'    field dia_rfc
    .                                                            "#EC CI_CCALL
  rc = sy-subrc .
endform.

*---------------------------------------------------------------------*
*       FORM SNC_JCB_MSG                                              *
*---------------------------------------------------------------------*
*  Erzeugen JCB Message Kernel Call                                   *
*---------------------------------------------------------------------*
form snc_jcb_msg
  using mes_nr type i                  " Message Number
        var1   type i                  " 1. Variable (int !)
        var2   type c .                " 2. Variable (char ggf ' ' )

  data: l_work(12) type c.
  l_work = var1 .
  condense l_work.
  if var2 is initial.
    call 'LOGIN_FOR_SNC_SERVER'
      id  'MSG_NR'      field mes_nr
      id  'VAR1'        field l_work .                           "#EC CI_CCALL
  else.
    call 'LOGIN_FOR_SNC_SERVER'
      id  'MSG_NR'      field mes_nr
      id  'VAR1'        field l_work
      id  'VAR2'        field var2 .                             "#EC CI_CCALL
  endif.
endform.



*---------------------------------------------------------------------*
*       FORM AUDIT_WRITE_ENTRY                                        *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  AREA                                                          *
*  -->  SUBID                                                         *
*---------------------------------------------------------------------*
form audit_write_entry
  using area  like tsl1d-area
        subid like tsl1d-subid.

* Diag Login ok      AU1
* Diag Login failed  AU2
* Logoff             AUC (nicht m?glich, da Message kein Parameter hat)

  data: key(3),
        ltsl1d like tsl1d,
        rsaudata(64).                  "L?nge = RSAUDATALG

  check area = 'AU'
    and ( subid = '1' or subid = '2' ).

  select single * from tsl1d into ltsl1d
    where area  = area
      and subid = subid.
  check sy-subrc = 0.

  key   = ltsl1d-area.
  key+2 = ltsl1d-subid.

  case subid.
  when '1'.
    concatenate 'RFC_' usr02-bname '&0&' into rsaudata.
  when '2'.
    concatenate 'RFC_' usr02-bname '&1&' into rsaudata.
  endcase.

  call 'AUDIT_WRITE_ENTRY'             "rsaua02_write_audit_entry
       id 'TYP'      field 'q'         "RSAUTYau
       id 'KEY'      field key
       id 'CLASS'    field ltsl1d-subclasid
       id 'SEVERITY' field ltsl1d-severity
       id 'DATA'     field rsaudata.                             "#EC CI_CCALL
endform.

*&---------------------------------------------------------------------*
*&      Form  CHECK_MULTI_LOGON
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form check_multi_logon.
  tables usr41.
  data: int41       like usr41 occurs 10 with header line.
  data: opcode_usr_attr(1)  type x value 5,
        terminal            like usr41-terminal,
        tid                 like usr41-termid,
        host                like usr41-server,
        hostaddr            like msxxlist-hostadr,
        act_sessions        like sm04dic-counter,
        max_sessions        like sm04dic-counter,
        my_session          like sm04dic-counter,
        my_internal_session like sm04dic-counter.
  data: my_servername       like msxxlist-name,
        my_terminalname     like usr41-terminal.
*       Flags und Indices
  data: single_login        type i value 0,
        single_terminal     type i value 0,
        check_other         type i value 0,
        systemtype(10)      type c.

  clear:   multi_logons. "Anzahl anderer Anmeldungen des gleichen Users
  refresh: multi_logon_tab.  "Liste: weitere bestehende Anmeldungen (TC)

** Haben wir ein Mehrfachanmeldungs-Frontend (z.B. ITS) ?
*  CALL 'MULTI_LOGIN_ALLOWED'.
*  IF SY-SUBRC = 0.
*    EXIT.
*  ENDIF.

* Soll der User ueberprueft werden? (default: ja!)
  call 'C_SAPGPARAM'   id 'NAME' field 'transport/systemtype'
                       id 'VALUE' field systemtype.              "#EC CI_CCALL
  if sy-subrc = 0 and systemtype = 'SAP'.
    single_login = 0.    "für SAP-interne System: Mehrfachanmeldung
    single_terminal = 1. "nur bei unterschiedl. Terminals beanstanden
  else.
    single_login = 1.    "für Kundensysteme: Mehrfachanmeldung stets
    single_terminal = 0. "beanstanden - auch bei gleichem Terminal
  endif.

* Mehrfachanmeldung ueberpruefen ...

* Eigene Terminal-Id feststellen
  call 'ThUsrInfo' id 'OPCODE' field opcode_usr_attr
    id 'TERMINAL' field terminal
    id 'TID' field tid
    id 'HOST' field host
    id 'HOSTADDR' field hostaddr
    id 'ACT_SESSIONS' field act_sessions
    id 'MAX_SESSIONS' field max_sessions
    id 'MY_SESSION' field my_session
    id 'MY_INTERNAL_SESSION' field my_internal_session.          "#EC CI_CCALL

* Eigene Server-Id ermitteln
  call 'C_SAPGPARAM'   id 'NAME' field 'rdisp/myname'
                       id 'VALUE' field my_servername.           "#EC CI_CCALL

* Weitere Anmeldungen des eigenen Benutzers ermitteln
  select      * from  usr41   client specified
         into   table int41
         where  mandt       = rsyst-mandt
         and    bname       = rsyst-bname.

* Ist nur die eine neue Anmeldung gefunden worden? (ja ==> EXIT)
* CHECK: SY-DBCNT > 1.
* CHECK: SY-DBCNT > 0.  "aktuelle Anmeldung ist noch nicht eingetragen!
  if sy-dbcnt = 0.
    clear: multi_logons. "nachfolgende PBO-/PAI-Modulen pruefen darauf!
    rsyst-pf25 = 'SKIP'. "PAI-Module pruefen darauf!
    suppress dialog.
    exit.
  endif.

* Für Single_Terminal die eigene Terminal-Bezeichnung feststellen
* IF SINGLE_TERMINAL = 1.
*    READ TABLE INT41 WITH KEY TERMID = TID
*                              SERVER = MY_SERVERNAME.
*    IF SY-SUBRC = 0.
*      MY_TERMINALNAME = INT41-TERMINAL.
*    ENDIF.
* ENDIF.

* Für alle Anmeldungen au?er der neuen
  loop at int41.
*   IF INT41-TERMID = TID AND INT41-SERVER = MY_SERVERNAME. "skip!
*   ELSE.

* Popup, wenn a) Single_Login
*             b) Single_Terminal und verschiedene Terminals entdeckt
      if ( single_login = 1 ) or
*        ( SINGLE_TERMINAL = 1 AND INT41-TERMINAL <> MY_TERMINALNAME ).
         ( single_terminal = 1 and int41-terminal ns terminal ).

* Prüfen, ob die andere gefundene Anmeldung tats?chlich noch existiert
        perform check_other_login using my_servername
                                        int41-server
                                        int41-termid
                               changing check_other.
        if check_other = 1.
*         trage andere Anmeldung in die Liste MULTI_LOGON_TAB ein
          clear: multi_logon_tab.
          multi_logon_tab-server     = int41-server.
          multi_logon_tab-terminal   = int41-terminal.
          multi_logon_tab-termid     = int41-termid.  "invisible data
          multi_logon_tab-logon_date = int41-logon_date.
          multi_logon_tab-logon_time = int41-logon_time.
          append multi_logon_tab.
        endif.
      endif.                "Andere Anmeldung oder anderes Terminal
*   ENDIF.                  "für alle Anmeldungen au?er dieser
  endloop.                  "über alle Anmeldungen (int41)

* ggf. Popup (Dynpro 500) anzeigen und Reaktionen auswerten
describe table multi_logon_tab lines multi_logons.
*CHECK: MULTI_LOGONS > 0.
if multi_logons = 0.
  rsyst-pf25 = 'SKIP'. "PAI-Module pruefen darauf!
  suppress dialog.
  exit.
endif.

sort multi_logon_tab by logon_date logon_time terminal.

* alle Pruefungen und Aktionen finden zu PBO bzw. PAI des Dynpros statt
*CALL SCREEN 500 STARTING AT 10 10.

endform.                               " CHECK_MULTI_LOGON


*&---------------------------------------------------------------------*
*&      Form  LOG_MULTI_LOGON
*&---------------------------------------------------------------------*
*       Protokollierung von mehrfachen Dialoganmeldungen (USR41_MLD)
*----------------------------------------------------------------------*
*  -->  MANDT     Mandant
*       BNAME     Benutzername
*       DATE      Datum
*       TIME      Uhrzeit
*       SESSIONS  Anzahl aktuell simultaner Dialoganmeldungen dieses B.
*
*  <--  <none>
*
*  12.03.1999   Wolfgang Janzen
*----------------------------------------------------------------------*
form log_multi_logon using mandt like usr41-mandt
                           bname like usr41-bname
                           date  like usr41-logon_date
                           time  like usr41-logon_time
                           sessions type i.
  tables: usr41_mld.

  select single for update * from usr41_mld client specified
       where  mandt     = mandt
       and    bname     = bname
       and    cal_year  = date(4).
* prepared for future extension: histogram ==> define PEAK as key field

  case sy-subrc.
    when 0.
*     existing entry found ==> update (prevents unlimited table growth)
      usr41_mld-last_date = date.
      usr41_mld-last_time = time.
      add 1 to usr41_mld-counter.
      if usr41_mld-peak <= sessions.   "update PEAK every time ...
        usr41_mld-peak = sessions.
        usr41_mld-peak_date = date.
        usr41_mld-peak_time = time.
      endif.
      update usr41_mld.

    when 4.
*     new entry ==> insert
      clear: usr41_mld.
      usr41_mld-mandt = mandt.
      usr41_mld-bname = bname.
      usr41_mld-first_date = usr41_mld-last_date = usr41_mld-peak_date
        = date.
      usr41_mld-first_time = usr41_mld-last_time = usr41_mld-peak_time
        = time.
      usr41_mld-cal_year = date(4).
      usr41_mld-counter = 1.
      usr41_mld-peak = sessions.
      insert usr41_mld.

    when others. "severe error !!!
*     ignore ...
  endcase.
endform.                    " LOG_MULTI_LOGON


*&---------------------------------------------------------------------*
*&      Form  GETPARAM
*&---------------------------------------------------------------------*
*       single_login_users und multi_login_users
*       sollen per Profilparameter eingelesen werden.
*----------------------------------------------------------------------*
*  -->  param       Profileparametername
*  <--  login_flag  = 0 ("Benutzer gehoert nicht zur Menge")
*                   = 1 ("Benutzer gehoert zu dieser Menge")
*----------------------------------------------------------------------*
form getparam using param changing login_flag.
*  data: login_users(300) type c, (note 1098186)
  data: login_users(3000) type c,
        users like usr02-bname occurs 0 with header line,
        user_char(1)    type c,
        user       like rsyst-bname,
        bname      like rsyst-bname,
        len        type i.

* Profilparameter einlesen
  call 'C_SAPGPARAM'
         id 'NAME' field param
         id 'VALUE' field login_users.                           "#EC CI_CCALL
  if sy-subrc = 4.
*   Profileparameter nicht gesetzt ==> Defaultwerte
*   CASE PARAM.
*     WHEN 'login/single_login_users'.
*     Bedeutung: diese Benutzer dürfen sich nur einmalig anmelden
*     Default: '*' (d.h. ausnahmslos jeder)
*       LOGIN_USERS = '*'.
*     WHEN 'login/single_terminal_users'.
*     Bedeutung: diese Benutzer dürfen sich von einem Terminal mehrfach
*                anmelden - jedoch nicht mehrfach von unterschiedlichen
*     Default: '' (d.h. niemand)
*       CLEAR LOGIN_USERS.
*     WHEN 'login/multi_login_users'.
*     Bedeutung: diese Benutzer dürfen sich ausdrücklich mehrfach
*                anmelden (dominiert alle anderen Regelungen!)
*     Default: '' (d.h. niemand)
        clear login_users.
*   ENDCASE.
  endif.

* Sonderfaelle: login_users = ''  -> keiner
*               login_users = '*' -> alle
  if login_users = ''.
    login_flag = 0.
  else.
*   IF LOGIN_USERS = '*'.
*     LOGIN_FLAG = 1.
*   ELSE.
      split login_users at ',' into table users.
      login_flag = 0.
      loop at users.
*       LEN = STRLEN( USERS ) - 1.
*       MOVE USERS+LEN(1) TO USER_CHAR.
*       IF USER_CHAR = '*'.            "Wildcard am Ende
*         MOVE RSYST-BNAME(LEN) TO BNAME.
*         MOVE USERS(LEN)       TO USER.
*         IF BNAME = USER.
*           LOGIN_FLAG = 1.
*           EXIT.
*         ENDIF.
*       ELSE.
          if rsyst-bname = users.
            login_flag = 1.
            exit.
          endif.
*       ENDIF.
      endloop.
*   ENDIF.
  endif.


endform.                               " GETPARAM

*---------------------------------------------------------------------*
*       FORM CHECK_OTHER_LOGIN                                        *
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
*  -->  THIS_SERVER                                                   *
*  -->  OTHER_SERVER                                                  *
*  -->  OTHER_TERMID                                                  *
*  -->  CHECK_OTHER                                                   *
*---------------------------------------------------------------------*
form check_other_login using this_server
                             other_server
                             other_termid
                    changing check_other.

  data: user_list type uinfo occurs 20 with header line,
      server_list type msxxlist occurs 20 with header line,
        msg_text(80) type c,           "Message text
        rfc_err type i value 0,
        clear_usr41 type i value 0.

  check_other = 0.                     " Default return: kein Popup

  if this_server = other_server.
    call function 'TH_USER_LIST'
         tables
              list = user_list.
  else.
*   Zun?chst feststellen, ob Server noch da ist
    call function 'TH_SERVER_LIST'
*    EXPORTING
*         SERVICES       = 255
         tables
              list           = server_list
         exceptions
              no_server_list = 1
              others         = 2.
    if sy-subrc <> 0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*       WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    else.
      read table server_list with key name = other_server.
      if sy-subrc <> 0.                "nicht gefunden, usr41 aufr?umen
        clear_usr41 = 1.
        rfc_err = 1.        "würden wir kriegen, da Server nicht da
      else.
        call function 'TH_USER_LIST'
          destination other_server
             tables
               list = user_list
             exceptions
               communication_failure = 1 message msg_text
               system_failure        = 2 message msg_text
               others = 3.
        if sy-subrc <> 0.
*         write: msg_text.
          rfc_err = 1.
        endif.
      endif.
    endif.
  endif.

  if rfc_err = 0.

    read table user_list with key tid =   other_termid
                                  mandt = rsyst-mandt
                                  bname = rsyst-bname.

    if sy-subrc <> 0.                  "nicht gefunden, usr41 aufr?umen
      clear_usr41 = 1.
    else.
      check_other = 1.                 "gefunden, Popup bringen
    endif.
  endif.

  if clear_usr41 = 1.
    delete from   usr41 client specified
           where  mandt       = rsyst-mandt
           and    bname       = rsyst-bname
           and    termid      = other_termid
           and    server      = other_server.
  endif.
endform.



*----------------------------------------------------------------------*
*       Display Login Scrren Info
*       Display SAPScript text LOGIN_SCREEN_INFO if it exists
*----------------------------------------------------------------------*
data: info_tab_cursor type i,
      info_tab        like tline        occurs 0 with header line.
*&---------------------------------------------------------------------*
*&      Module  FILL_INFO_TAB OUTPUT
*&---------------------------------------------------------------------*
module fill_info_tab output.
  perform fill_info_tab.
endmodule.
*
form fill_info_tab.
  statics: login_info_text_found.

  data: docu_id     like dokhl-id     value 'TX',
        docu_langu  like dokhl-langu,
        docu_object like dokhl-object value 'ZLOGIN_SCREEN_INFO',
        docu_typ    like dokhl-typ    value 'E',
*       docu_found,
        docu_xdokil like dokil.

  check login_info_text_found is initial.

  if login_info_text_found = 'N'.
*   No Login Info Text exist (deactivate screen fields)
    exit.
  endif.

  docu_langu = sy-langu.
  IF docu_langu eq space.
* Default language
    call 'C_SAPGPARAM'
      id 'NAME' field 'zcsa/system_language'
      id 'VALUE' field docu_langu.                                 "#EC CI_CCALL
  ENDIF.

* SAPScript text exists?
*  call function 'DOCU_INIT'
*       exporting
*            id      = docu_id
*            langu   = docu_langu
*            object  = docu_object
*            typ     = docu_typ
*       importing
*            found   = docu_found
*            xdokil  = docu_xdokil
*            .
  data: I_DOKIL LIKE DOKIL.
  SELECT SINGLE *
      FROM  DOKIL
      into  docu_xdokil
      WHERE ID         = docu_id
      AND   OBJECT     = docu_object
      AND   LANGU      = docu_langu
      AND   TYP        = docu_typ.

  IF sy-subrc NE 0 OR docu_xdokil-txtlines = 0.
*   Fallback to system language (downwards-compatibility)
    CALL 'C_SAPGPARAM'
      ID 'NAME' FIELD 'zcsa/system_language'
      ID 'VALUE' FIELD docu_langu.                          "#EC CI_CCALL

    SELECT SINGLE *
        FROM  dokil
        INTO  docu_xdokil
        WHERE id         = docu_id
        AND   object     = docu_object
        AND   langu      = docu_langu
        AND   typ        = docu_typ.
  ENDIF.

* if docu_found ne 0.
  if SY-SUBRC ne 0 or docu_xdokil-txtlines = 0.
    login_info_text_found = 'N'.
    loop at screen.
      if screen-group1 = 'MSG'.
        screen-active = 0.
        modify screen.
      endif.
    endloop.
    exit.
  endif.

*  call function 'DOCU_READ'
*       exporting
*            id                = docu_xdokil-id
*            langu             = docu_xdokil-langu
*            object            = docu_xdokil-object
*            typ               = docu_xdokil-typ
*            version           = docu_xdokil-version
*            suppress_template = 'X'
**           USE_NOTE_TEMPLATE = ' '
**      IMPORTING
**           DOKTITLE          = docu_title
**           HEAD              =
*       tables
*            line              = info_tab
*            .
  data: IT_DOKTL LIKE DOKTL occurs 0 with header line.
  SELECT *
    FROM  doktl
    INTO  TABLE it_doktl
    WHERE langu      =  docu_xdokil-langu
    AND   id         =  docu_xdokil-id
    AND   object     =  docu_xdokil-object
    AND   typ        =  docu_xdokil-typ
    AND   dokversion =  docu_xdokil-version
    ORDER BY PRIMARY KEY.
  clear info_tab[].
  loop at it_doktl.
    MOVE IT_DOKTL-DOKFORMAT TO info_tab-TDFORMAT.
    MOVE IT_DOKTL-DOKTEXT   TO info_tab-TDLINE.
    IF info_tab-TDLINE(1) LT SPACE.
      MOVE SPACE TO info_tab-TDLINE.
    ENDIF.
    append info_tab.
  endloop.

  login_info_text_found = 'Y'.
endform.

*&---------------------------------------------------------------------*
*&      Module  SHOW_INFO_TAB  OUTPUT
*&---------------------------------------------------------------------*
module show_info_tab output.
* Highlight heading lines (Format 'U*')
  read table info_tab index info_tab_cursor.
  if info_tab-tdformat(1) = 'U'.
    loop at screen.
      if screen-name = 'INFO_TAB-TDLINE'.
        screen-intensified = 1.
        modify screen.
      endif.
    endloop.
  endif.
endmodule.                 " SHOW_INFO_TAB  OUTPUT

*=======================================================================
*                 Dynpro 500   (Multiple Dialog Logon)
*=======================================================================


*&---------------------------------------------------------------------*
*&      Module  CHECK_MULTI_LOGON  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module check_multi_logon output.
  clear:     rsyst-pf25.       "OK-Code
  if multi_logon_check_called is initial.
     clear:  multi_logon_opt1, "andere, bestehende Sitzungen abbrechen
             multi_logon_opt2, "mit allen Sitzungen weiterarbeiten
             multi_logon_opt3. "diesen Anmeldeversuch abbrechen
     perform check_multi_logon.
  endif.
endmodule.                 " CHECK_MULTI_LOGON  OUTPUT


*&---------------------------------------------------------------------*
*&      Module  HANDLE_MULTI_LOGON_USERS  OUTPUT
*&---------------------------------------------------------------------*
*       Profileparameter 'login/multi_login_users' behandeln
*       ==> ggf. Option 2 vorgeben (dabei Dynpro unterdrücken)
*----------------------------------------------------------------------*
*       'login/disable_multi_gui_login = 1' hat eine NIEDRIGERE
*       Prioritaet als 'login/multi_login_users' ... !!!
*----------------------------------------------------------------------*
module handle_multi_logon_users output.
* vorab: Ist ueberhaupt etwas zu tun ...?!
  check: multi_logons > 0.
  check: multi_logon_check_called is initial.

* Soll fuer diesen Benutzer die Mehrfachanmeldung stets ohne Rueckfrage
* (==> siehe aeltere Releases, aber jetzt mit Protokollierung) moeglich
* sein?
  perform getparam using    'login/multi_login_users'
                   changing multi_login_user.
  if multi_login_user = 1.
*    Default-Option = "akzeptiere Mehrfachanmeldung" (==> Protokoll.)
     multi_logon_opt2 = 'X'.
     rsyst-pf25 = 'OK'.
     suppress dialog.  "weitere PBO-Module werden aber durchlaufen!
  else.
*    Default-Option = "beende diese Anmeldung"
     multi_logon_opt3 = 'X'.
     clear: rsyst-pf25.
  endif.
endmodule.                 " HANDLE_MULTI_LOGON_USERS  OUTPUT


*&---------------------------------------------------------------------*
*&      Module  HANDLE_MULTI_LOGON_DISABLED  OUTPUT
*&---------------------------------------------------------------------*
*       Profileparameter 'login/disable_multi_gui_login' behandeln
*       ==> ggf. Option 2 ausblenden
*----------------------------------------------------------------------*
*  ACHTUNG:  Profileparameter 'login/multi_login_users' (a) hat eine
*            hoehere Prioritaet als 'login/disable_multi_gui_login' (b)
*       ==>  (a) unterdrueckt das Dynpro komplett waehrend (b) nur die
*            Option 2 ausblendet; Grund: (a) hat Notankerfunktion!
*----------------------------------------------------------------------*
module handle_multi_logon_disabled output.
* vorab: Ist ueberhaupt etwas zu tun ...?!
  check: multi_logons > 0.
* check: multi_logon_check_called is initial.  "Hinweis 453052

* Profileparameter 'login/multi_login_users' hat hoehere Prioritaet!
  check: multi_login_user = 0.

* Profileparameter 'login/disable_multi_gui_login' auswerten ...
  call 'C_SAPGPARAM' id 'NAME' field 'login/disable_multi_gui_login'
                     id 'VALUE' field multi_logon_disabled.      "#EC CI_CCALL
  if ( sy-subrc = 0 ) and ( multi_logon_disabled = '1' ).
*   Option 2 (Multilogon) des Dynpros 500 ausblenden
    loop at screen.
      if screen-group1 = 'OP2'.
        screen-active = 0.
        modify screen.
      endif.
    endloop.
*   Meldung "Mehrfachanmeldung vom Systemadministrator untersagt"
    message i155.
*   Benutzer ist an einem anderen Bildschirm angemeldet
  else.
*   Defaultwert setzen
    multi_logon_disabled = 0.
  endif.
endmodule.                 " HANDLE_MULTI_LOGON_DISABLED  OUTPUT


*&---------------------------------------------------------------------*
*&      Module  SET_MULTI_LOGON_TEXT  OUTPUT
*&---------------------------------------------------------------------*
*       PBO zu Dynpro 500 (Lizenzinformationen bei Mehrfachanmeldung)
*----------------------------------------------------------------------*
data: i type i,
      tc_cols type CXTAB_COLUMN,
      date(10),
      time(8).
*
module set_multi_logon_text output.
* vorab: Ist ueberhaupt etwas zu tun ...?!
  check: multi_logons > 0.
  check: multi_logon_check_called is initial.

  multi_logon_check_called = 'X'.

* Profileparameter 'login/multi_login_users' hat hoehere Prioritaet!
* (da dann ohnehin SUPPRESS DIALOG ausgefuehrt wird, koennen die
*  nachfolgenden Dynprofeldwert-Initialisierungen ausgelassen werden)
  check: multi_login_user = 0.

 set pf-status '500'.
 set titlebar '500'.
* fehlt noch: Deaktivieren von "Create Session"-M?glichkeit (SAPGUI)
 multi_logon_text = text-500.
 replace '&1' with rsyst-bname into multi_logon_text.
 replace '&2' with rsyst-mandt into multi_logon_text.
 condense multi_logon_text.

* nur bei mehrzeiligen Angaben wird TableControl angezeigt
 describe table multi_logon_tab lines i.
 if i = 1.
   loop at screen.
     if screen-name = 'MULTI_LOGON_TEXT2'.
        screen-invisible = 0. modify screen.
     endif.
     if screen-group1 = 'TC'.
        screen-invisible = 1.
        screen-active = 0.
        modify screen.
     endif.
   endloop.

   multi_logon_tc-invisible = 1.
   loop at multi_logon_tc-cols into tc_cols.
    tc_cols-invisible = 'X'.
    tc_cols-screen-active = 0.
    modify multi_logon_tc-cols from tc_cols.
   endloop.

   read table multi_logon_tab index 1.  "es gibt nur diese eine Zeile!
   multi_logon_text2 = text-501.
   replace '&3' with multi_logon_tab-terminal   into multi_logon_text2.
   write multi_logon_tab-logon_date to date dd/mm/yyyy.
   replace '&4' with date into multi_logon_text2.
   write multi_logon_tab-logon_time to time using edit mask '__:__:__'.
   replace '&5' with time into multi_logon_text2.
   condense multi_logon_text2.
   replace ' ",' with '",' into multi_logon_text2.
 endif.
endmodule.                 " SET_MULTI_LOGON_TEXT  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0500  INPUT
*&---------------------------------------------------------------------*
*       PAI zu Dynpro 500 (Lizenzinformationen bei Mehrfachanmeldung)
*----------------------------------------------------------------------*
module user_command_0500 input.

* zu PAI nochmals aktuellen Stand überprüfen ...!
* (es kann zwischenzeitlich zu Mehrfachanmeldungen gekommen sein)
* (Trigger: Kundenmeldung 0020079747 0000085719 2002)
  perform check_multi_logon.

* vorab: Ist ueberhaupt etwas zu tun ...?! (sonst: OK-Code == 'SKIP')
  if multi_logons > 0.

* Falls jemand auf "Abbrechen" drückt, so soll dies ?quivalent zur
* Auswahl von Option 3 (Default) sein ==> harte Abmeldung vom System
    if rsyst-pf25 = 'CANC'.
      call 'SYST_LOGOFF'.                                        "#EC CI_CCALL
    endif.

* Benutzer hat sich bewu?t für eine der Optionen 1-3 entschieden
    if rsyst-pf25 = 'OK'.

      if not  multi_logon_opt3 is initial.
*      "Aktuelle Anmeldung abbrechen"
        call 'SYST_LOGOFF'.                                      "#EC CI_CCALL

      elseif not multi_logon_opt1 is initial.
*      "Mit dieser Anmeldung fortfahren und alle bestehenden
*        Anmeldungen beenden"
        loop at multi_logon_tab.
          call 'ThSndDelUser'
            id 'MANDT'  field rsyst-mandt
            id 'BNAME'  field rsyst-bname
            id 'SERVER' field multi_logon_tab-server
            id 'TID'    field multi_logon_tab-termid.            "#EC CI_CCALL
        endloop.

      elseif not multi_logon_opt2 is initial.
*      "Mit dieser Anmeldung fortfahren, ohne bestehende Anmeldungen zu
*       beenden" (wissentliche Mehrfachanmeldung) ==> Protokollierung!
        add 1 to multi_logons. "aktuelle Anmeldung hinzuzaehlen!
*       Protokollierung der Mehrfachdialoganmeldung (==> USR41_MLD).
        perform log_multi_logon using rsyst-mandt
                                      rsyst-bname
                                      sy-datum
                                      sy-uzeit
                                      multi_logons.

     endif. "Behandlung der MULTI_LOGON_OPT#
   endif. "Abfrage auf RSYST-PF25 == 'OK'
 else.
*  es liegt keine Mehrfachanmeldung vor (MULTI_LOGONS == 0)
"  RSYST-PF25 = 'SKIP'.
endif.
*leave to screen 0.  "==> jetzt in SYST-SIGNM (Kernel)
endmodule.                 " USER_COMMAND_0500  INPUT


*======================================================================*
* Dynpro 0041: Kennwort?nderungspopup bei Kennwortanmeldung (SAPGUI)
*======================================================================*
MODULE INFO_CASESENSITIVE_PWD OUTPUT.

* login/password_downwards_compatibility auswerten
  call 'C_SAPGPARAM'  ID 'NAME'  FIELD 'login/password_downwards_compatibility'
                      ID 'VALUE' FIELD password_downwards_comp.  "#EC CI_CCALL
  if sy-subrc <> 0.
    password_downwards_comp = '1'.  "default
  endif.

  if password_downwards_comp = '5'.
    loop at screen.
      if screen-name = 'INFO_CASESENSITIVE_PWD'.
         screen-active = 0.
         modify screen.
      endif.
      if screen-group3 = 'PWD'.
         screen-length = 8.
         modify screen.
      endif.
    endloop.
  endif.

* aktuelles Kennwort: Codeversion ermitteln
  data: codvn like usr02-codvn.
  select single codvn into codvn
      from usr02 where bname = sy-uname.
  if sy-subrc = 0 and
    ( codvn = 'A' or
      codvn = 'B' or
      codvn = 'C' or
      codvn = 'D' or
      codvn = 'E' ).

      loop at screen.
        if screen-group3 = 'OPW'.
           screen-length = 8.
           modify screen.
        endif.
      endloop.
  endif.
ENDMODULE.

*======================================================================*
* Dynpro 0042: Kennwort?nderungspopup bei SSO-Anmeldung per SAPGUI
*======================================================================*

*&---------------------------------------------------------------------*
*&      Module  STATUS_0042  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE STATUS_0042 OUTPUT.
  SET PF-STATUS '0042'.
  SET TITLEBAR '042'.

* determine value of Security Policy Attribute PASSWORD_CHANGE_FOR_SSO
  SELECT SINGLE security_policy FROM usr02 INTO policy WHERE bname = sy-uname.
  IF sy-subrc <> 0.
    CLEAR policy.
  ENDIF.
  TRY.
*   policy = SPACE -> evaluate profile parameter login/password_change_for_SSO
    password_change_for_SSO = cl_security_policy=>get_attribute_value(   policy = policy
                                                                         attribute = 'PASSWORD_CHANGE_FOR_SSO' ).
    CATCH cx_security_policy.
      TRY.
          password_change_for_SSO = cl_security_policy_attribute=>get_default_value( 'PASSWORD_CHANGE_FOR_SSO' ).
        CATCH cx_security_policy.
          password_change_for_SSO = 1. "default value (hard-coded)
      ENDTRY.
  ENDTRY.
* Evaluation of password_change_for_SSO is shifted to the end of this PBO module (see below)

* INTROTEXT1: Authentisierungsmethode
  INTROTEXT1 = 'Sie wurden mittels & authentisiert.'(420).
  call 'LOGIN_INFO' ID 'OPCODE'    FIELD session_info
                    ID 'AUTH_TYPE' FIELD auth_type.              "#EC CI_CCALL
  if sy-subrc = 0.

    if auth_type = 's'. "HTTP Security Session
      TRY.
          l_sec_context = cl_http_security_session_admin=>get_current_session_context( ).
        CATCH cx_http_security_session_admin.
          CLEAR l_sec_context.
      ENDTRY.
      IF l_sec_context IS NOT INITIAL.
        CALL METHOD cl_http_security_session_admin=>decompose_authnmethods_field
          EXPORTING
            authnmethods         = l_sec_context-authnmethods
          IMPORTING
            authnmethod_password = l_pwd_logon.
        IF l_pwd_logon = abap_true.
          auth_type = 'P'.
        ENDIF.
      ENDIF.
    endif.

    case auth_type.
      when 'P'.  replace '&' in INTROTEXT1
                   with 'Kennwort'(430).
                 password_change_for_SSO = 2. "Option 'Kennwort deaktivieren' ausblenden
      when 'X'.  replace '&' in INTROTEXT1
                   with 'X.509-Clientzertifikat'(431).
      when 'E'.  replace '&' in INTROTEXT1
                   with 'externer Benutzerauthentisierung'(432).
      when 'T'.  replace '&' in INTROTEXT1
                   with 'SAP Anmeldeticket'(433).
      when 'S'.  replace '&' in INTROTEXT1
                   with 'SNC (Secure Network Communication)'(434).
      when 'R'.  replace '&' in INTROTEXT1
                   with 'RFC Trusted System'(435).
    endcase.
  endif.

* INTROTEXT3: Grund für Kennwort?nderungspflicht
  INTROTEXT3 = '(Grund: Kennwort ist &)'(421).
  call 'PASSWORD' ID 'OPCODE'   FIELD 'S'
                  ID 'USERNAME' FIELD SY-UNAME
                  ID 'PASSFLAG' FIELD PWDSTATE.                  "#EC CI_CCALL
  if sy-subrc = 0.
    case pwdstate.
      when  1. replace '&' in INTROTEXT3 with 'initial'(422).
      when  2. replace '&' in INTROTEXT3 with 'abgelaufen'(423).
      when  3. INTROTEXT3 = '(Grund: Kennwortregeln wurden versch?rft)'(424).
      when -1. message E180(00). "Kennwort nur einmal t?glich ?ndern
      when -2. message E190(00). "Kennwort kann nicht ge?ndert werden
      when -3. message E139(00). "Kennwortanmeldung deaktiviert
      when -4. message E197(00). "Sie besitzen kein Kennwort
    endcase.
  endif.

* shifted to the end since a detected password usage might have changed
* the value of variable password_change_for_SSO (= 2)
  case password_change_for_SSO.
    when 0. "sofort abbrechen
            suppress dialog. exit.
    when 1. "beide Optionen anbieten
    when 2. "Option 'Kennwort deaktivieren' ausblenden
            set PF-STATUS '0042' excluding 'DELETE'.
            loop at screen.
              if screen-group1 = 'DEL'.
                screen-active = 0.
                modify screen.
              endif.
            endloop.
    when 3. "Auswahl der Option 'Kennwort deaktivieren'
            suppress dialog. exit.
  endcase.

ENDMODULE.                 " STATUS_0042  OUTPUT


*&---------------------------------------------------------------------*
*&      Module  CHECK_PASSWORD_0042  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE CHECK_PASSWORD_0042 INPUT.

  check: RSYST-FCODE = 'CHANGE'.

  if RSYST-BCODE is initial.
    set cursor field RSYST-BCODE.
    message e290(00). "Bitte altes Kennwort eingeben
  endif.

  if RSYST-NCODE is initial.
    clear: RSYST-NCOD2.
    set cursor field RSYST-NCODE.
    message e153(00). "Bitte neues Kennwort eingeben
  endif.

* login/password_downwards_compatibility auswerten
  call 'C_SAPGPARAM'  ID 'NAME'  FIELD 'login/password_downwards_compatibility'
                      ID 'VALUE' FIELD password_downwards_comp.  "#EC CI_CCALL
  if sy-subrc <> 0.
    password_downwards_comp = '1'.  "default
  endif.
  if password_downwards_comp = '5'.
    TRANSLATE RSYST-NCODE to UPPER CASE.
    TRANSLATE RSYST-NCOD2 to UPPER CASE.
  endif.
  if RSYST-NCODE <> RSYST-NCOD2.
    clear: RSYST-NCODE, RSYST-NCOD2.
    set cursor field RSYST-NCODE.
    message e184(00). "Bitte Kennworte übereinstimmend eingeben
  endif.

  call 'PASSWORD' ID 'OPCODE'   FIELD 'C'
                  ID 'USERNAME' FIELD SY-UNAME
                  ID 'OLD_PWD'  FIELD RSYST-BCODE
                  ID 'NEW_PWD'  FIELD RSYST-NCODE
                  ID 'PASSFLAG' FIELD pwdstate
                  ID 'PWD_RC'   FIELD pwd_rc.                    "#EC CI_CCALL
  "Kernel l?st ggf. selbst E-Message aus
ENDMODULE.                 " CHECK_PASSWORD_0042  INPUT


*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0042  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_0042 INPUT.

  case password_change_for_SSO.
    when 0. "sofort abbrechen
            RSYST-FCODE = 'SILENT'.
    when 3. "stille Auswahl der Option 'Kennwort deaktivieren'
            RSYST-FCODE = 'DELETE'.
  endcase.

  case RSYST-FCODE.
    when 'DELETE'.
*      Kennwort deaktivieren
       call 'PASSWORD' ID 'OPCODE'   FIELD 'D'
                       ID 'USERNAME' FIELD SY-UNAME
                       ID 'PASSFLAG' FIELD pwdstate.             "#EC CI_CCALL
       message s291(00). "Ihr Kennwort wurde deaktiviert

    when 'CHANGE'.
*      Kennwort ?ndern (bereits in vorherigem PAI-Modul erfolgt)

    when 'CANCEL'.
*      Abbruch durch Benutzer (wird in PAI-Modul SYST-SIGNC behandelt)
  endcase.

ENDMODULE.                 " USER_COMMAND_0042  INPUT

*======================================================================*
* Dynpro 0043: Kennwort?nderungspopup
* Verwendung in Transaktion SU3
* Das Dynpro wird als Subscreen im Dynpro SAPLSUSR 0100 angezeigt
*======================================================================*

*&---------------------------------------------------------------------*
*&      Form  DYNPRO_0043_STATUS_CHECK
*&---------------------------------------------------------------------*
*       Fehlerprüfungen und -meldungen vor Kennwort?nderungspopup
*       Aufruf durch Funktionsbaustein SUSR_PASSWORD_CHANGE_DIALOG
*----------------------------------------------------------------------*
form DYNPRO_0043_STATUS_CHECK .
  data: pwdstate type XUPWDSTATE,
        msgarea  like sy-msgid,
        msgno    like sy-msgno,
        msgv1    like sy-msgv1,   "requires new kernel, otherwise: remains empty
        msgv2    like sy-msgv2.   "requires new kernel, otherwise: remains empty

* error situation? (display E-message and abort)
  call 'PASSWORD' ID 'OPCODE'   FIELD 'S'
                  ID 'USERNAME' FIELD SY-UNAME
                  ID 'MSGAREA'  FIELD MSGAREA
                  ID 'MSGNO'    FIELD MSGNO
                  ID 'MSGV1'    FIELD MSGV1   "requires new kernel
                  ID 'MSGV2'    FIELD MSGV2   "requires new kernel
                  ID 'PASSFLAG' FIELD PWDSTATE.                  "#EC CI_CCALL
  if sy-subrc = 0 and PWDSTATE < 0.
    message id MSGAREA type 'E' number MSGNO with MSGV1 MSGV2.
  endif.
endform.                    " DYNPRO_0043_STATUS_CHECK

*&---------------------------------------------------------------------*
*&      Form  DYNPRO_0043_SET_STATUS
*&---------------------------------------------------------------------*
*       Aufruf w?hrend PBO von Dynpros SAPLSUSR 0100
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form DYNPRO_0043_SET_STATUS .
  constants: session_info type x value 2.
  data: auth_type type c.

* determine value of Security Policy Attribute PASSWORD_CHANGE_FOR_SSO
  SELECT SINGLE security_policy FROM usr02 INTO policy WHERE bname = sy-uname.
  IF sy-subrc <> 0.
    CLEAR policy.
  ENDIF.
  TRY.
*   policy = SPACE -> evaluate profile parameter login/password_change_for_SSO
    password_change_for_SSO = cl_security_policy=>get_attribute_value(   policy = policy
                                                                         attribute = 'PASSWORD_CHANGE_FOR_SSO' ).
    CATCH cx_security_policy.
      TRY.
          password_change_for_SSO = cl_security_policy_attribute=>get_default_value( 'PASSWORD_CHANGE_FOR_SSO' ).
        CATCH cx_security_policy.
          password_change_for_SSO = 1. "default value (hard-coded)
      ENDTRY.
  ENDTRY.

* Authentisierungsmethode
  call 'LOGIN_INFO' ID 'OPCODE'    FIELD session_info
                    ID 'AUTH_TYPE' FIELD auth_type.              "#EC CI_CCALL

  if auth_type = 's'. "HTTP Security Session
    TRY.
        l_sec_context = cl_http_security_session_admin=>get_current_session_context( ).
      CATCH cx_http_security_session_admin.
        CLEAR l_sec_context.
    ENDTRY.
    IF l_sec_context IS NOT INITIAL.
      CALL METHOD cl_http_security_session_admin=>decompose_authnmethods_field
        EXPORTING
          authnmethods         = l_sec_context-authnmethods
        IMPORTING
          authnmethod_password = l_pwd_logon.
      IF l_pwd_logon = abap_true.
        auth_type = 'P'.
      ENDIF.
    ENDIF.
  endif.

  if password_change_for_SSO = 2
    or auth_type = 'P'.  " Authentisierungsmethode Password
*   Option 'Kennwort deaktivieren' ausblenden
    set pf-status 'PWDCHG' excluding 'DELETE' of program 'SAPMSYST'.
  else.
    set pf-status 'PWDCHG' of program 'SAPMSYST'.
  endif.
  set titlebar 'PWDCHG' of program 'SAPMSYST' with sy-uname.
endform.                    " DYNPRO_0043_SET_STATUS

*&---------------------------------------------------------------------*
*&      Module  STATUS_0043  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE STATUS_0043 OUTPUT.
  clear: RSYST-BCODE, RSYST-NCODE, RSYST-NCOD2.
* Kennwortstatus ermitteln
  call 'PASSWORD' ID 'OPCODE'   FIELD 'S'
                  ID 'USERNAME' FIELD SY-UNAME
                  ID 'PASSFLAG' FIELD PWDSTATE.                  "#EC CI_CCALL
  if sy-subrc <> 0.
    message E191(00). "Programmfehler
  else.
    if pwdstate < 0.
      "alles ausblenden ... (bis auf Fehlertextzeile)
      loop at screen.
        if screen-group1 <> 'ERR'.
          screen-active = 0.
          modify screen.
        endif.
      endloop.
      case pwdstate.
        when -1. ERRORTEXT =
'Sie k?nnen Ihr Kennwort nur 1x pro Tag ?ndern'(031).
        when -2. ERRORTEXT =
'Sie k?nnen Ihr Kennwort nicht ?ndern (Servicebenutzer).'(032).
        when -3. ERRORTEXT =
'Sie k?nnen sich an diesem System nicht per Kennwort anmelden.'(033).
        when -4. ERRORTEXT =
'Sie besitzen kein Kennwort - Kennwort?nderung nicht m?glich.'(034).
      endcase.
    else.
      "Fehlertextzeile ausblenden
      loop at screen.
        if screen-group1 = 'ERR'.
          screen-active = 0.
          modify screen.
        endif.
      endloop.
    endif.
  endif.

* determine value of Security Policy Attribute PASSWORD_CHANGE_FOR_SSO
  SELECT SINGLE security_policy FROM usr02 INTO policy WHERE bname = sy-uname.
  IF sy-subrc <> 0.
    CLEAR policy.
  ENDIF.
  TRY.
*   policy = SPACE -> evaluate profile parameter login/password_change_for_SSO
    password_change_for_SSO = cl_security_policy=>get_attribute_value(   policy = policy
                                                                         attribute = 'PASSWORD_CHANGE_FOR_SSO' ).
    CATCH cx_security_policy.
      TRY.
          password_change_for_SSO = cl_security_policy_attribute=>get_default_value( 'PASSWORD_CHANGE_FOR_SSO' ).
        CATCH cx_security_policy.
          password_change_for_SSO = 1. "default value (hard-coded)
      ENDTRY.
  ENDTRY.

* Authentisierungsmethode
  call 'LOGIN_INFO' ID 'OPCODE'    FIELD session_info
                    ID 'AUTH_TYPE' FIELD auth_type.              "#EC CI_CCALL

  if auth_type = 's'. "HTTP Security Session
    TRY.
        l_sec_context = cl_http_security_session_admin=>get_current_session_context( ).
      CATCH cx_http_security_session_admin.
        CLEAR l_sec_context.
    ENDTRY.
    IF l_sec_context IS NOT INITIAL.
      CALL METHOD cl_http_security_session_admin=>decompose_authnmethods_field
        EXPORTING
          authnmethods         = l_sec_context-authnmethods
        IMPORTING
          authnmethod_password = l_pwd_logon.
      IF l_pwd_logon = abap_true.
        auth_type = 'P'.
      ENDIF.
    ENDIF.
  endif.

* INTROTEXT1: Authentisierungsmethode
  INTROTEXT1 = 'Sie wurden mittels & authentisiert.'(420).

  case auth_type.
    when 'P'.  replace '&' in INTROTEXT1
                 with 'Kennwort'(430).
               password_change_for_SSO = 2. "Option 'Kennwort deaktivieren' ausblenden
    when 'X'.  replace '&' in INTROTEXT1
                 with 'X.509-Clientzertifikat'(431).
    when 'E'.  replace '&' in INTROTEXT1
                 with 'externer Benutzerauthentisierung'(432).
    when 'T'.  replace '&' in INTROTEXT1
                 with 'SAP Anmeldeticket'(433).
    when 'S'.  replace '&' in INTROTEXT1
                 with 'SNC (Secure Network Communication)'(434).
    when 'R'.  replace '&' in INTROTEXT1
                 with 'RFC Trusted System'(435).
    when 's'.  replace '&' in INTROTEXT1
                 with 'HTTP Security Session'(436).
    when '2'.  replace '&' in INTROTEXT1
                 with 'SAML 2.0'(437).
    when 'N'.  replace '&' in INTROTEXT1
                 with 'SPNego'(438).
    when 'a'.  replace '&' in INTROTEXT1
                 with 'APC-Session'(439).
    when others. replace '&' in INTROTEXT1 with auth_type.
  endcase.

* ggf. Felder 'Kennwort deaktivieren' ausblenden (Hinweis 942001)
  IF PASSWORD_CHANGE_FOR_SSO = 2
    OR AUTH_TYPE = 'P'.  " Authentisierungsmethode Password
    LOOP AT SCREEN.
      IF SCREEN-NAME = 'INTROTEXT1' OR
         SCREEN-NAME = 'INTROTEXT2' OR
         SCREEN-GROUP1 = 'DEL'.
           SCREEN-ACTIVE = 0.
           MODIFY SCREEN.
      ENDIF.
    ENDLOOP.
  ENDIF.

ENDMODULE.                 " STATUS_0043  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0043  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_0043 INPUT.

  case FCODE_0043.
    when 'DELETE'.
*      Kennwort deaktivieren
       call 'PASSWORD' ID 'OPCODE'   FIELD 'D'
                       ID 'USERNAME' FIELD SY-UNAME
                       ID 'PASSFLAG' FIELD pwdstate.             "#EC CI_CCALL
       message s291(00). "Ihr Kennwort wurde deaktiviert

    when 'CHANGE'.
*      Kennwort ?ndern
       if RSYST-BCODE is initial.
         set cursor field RSYST-BCODE.
         message e290(00). "Bitte altes Kennwort eingeben
       endif.

       if RSYST-NCODE is initial.
         clear: RSYST-NCOD2.
         set cursor field RSYST-NCODE.
         message e153(00). "Bitte neues Kennwort eingeben
       endif.


*      login/password_downwards_compatibility auswerten
       call 'C_SAPGPARAM'  ID 'NAME'  FIELD 'login/password_downwards_compatibility'
                           ID 'VALUE' FIELD password_downwards_comp.  "#EC CI_CCALL
       if sy-subrc <> 0.
         password_downwards_comp = '1'.  "default
       endif.
       if password_downwards_comp = '5'.
         TRANSLATE RSYST-NCODE to UPPER CASE.
         TRANSLATE RSYST-NCOD2 to UPPER CASE.
       endif.
       if RSYST-NCODE <> RSYST-NCOD2.
         clear: RSYST-NCODE, RSYST-NCOD2.
         set cursor field RSYST-NCODE.
         message e184(00). "Bitte Kennworte übereinstimmend eingeben
       endif.

       call 'PASSWORD' ID 'OPCODE'   FIELD 'C'
                       ID 'USERNAME' FIELD SY-UNAME
                       ID 'OLD_PWD'  FIELD RSYST-BCODE
                       ID 'NEW_PWD'  FIELD RSYST-NCODE
                       ID 'PASSFLAG' FIELD pwdstate
                       ID 'PWD_RC'   FIELD pwd_rc.               "#EC CI_CCALL
       "Kernel l?st ggf. selbst E-Message aus
  endcase.

ENDMODULE.                 " USER_COMMAND_0043  INPUT

*&---------------------------------------------------------------------*
*&      Form  DYNPRO_0043_PASS_FCODE          (to be called at PAI)
*&---------------------------------------------------------------------*
FORM DYNPRO_0043_PASS_FCODE USING FCODE.
  FCODE_0043 = FCODE.
ENDFORM.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值