Document-ID:        30860.1
Subject:            CUSTOMIZING LOGON BEHAVIOR
Author:             RNIX
Last Modified Date: 04 December  1995


                     Customizing Logon Behavior

Introduction
============
By default, Oracle Forms will attempt to establish a connection to a
database when starting up a Runform session.  If the connect
information (username, password, connect string) is not specified as
parameters to the Runform executable, Oracle Forms will pop up a logon
window.

This bulletin details methods of commonly-asked-for customization of
this logon behavior, including running a form without logging onto a
database, defaulting the connect string, and creating a custom logon
window.

Objective
=========
This bulletin will primarily focus on the On-Logon trigger and the
LOGON built-in.  The On-Logon trigger, if defined, replaces the
default logon behavior of Oracle Forms.  Within that trigger, the
LOGON built-in actually establishes the connection.  If called from
outside the On-Logon trigger, the LOGON built-in calls the On-Logon
trigger.

Running Without a Connection
============================
Forms that do not access any data do not require connections to the
database.  By telling Forms not to establish a connection, startup
time is reduced and the operator will not be prompted for connect
information.  The following On-Logon trigger eliminates logon
entirely:

  On-Logon (Form Level)
    NULL;

Small Changes to Default Behavior
=================================
Here is an On-Logon trigger which mimics the default behavior of
Oracle Forms when it performs a connect.

   On-Logon (Form Level)
      DECLARE
         un          VARCHAR2(30);
         pw          VARCHAR2(30);
         cs          VARCHAR2(30);
         upc         VARCHAR2(200);
         connected   BOOLEAN := FALSE;
         tries       NUMBER := 3;
         PROCEDURE get_connect_info IS
         BEGIN
            un := GET_APPLICATION_PROPERTY(USERNAME);
            pw := GET_APPLICATION_PROPERTY(PASSWORD);
            cs := GET_APPLICATION_PROPERTY(CONNECT_STRING);
         END;
      BEGIN
         get_connect_info;
         IF un IS NOT NULL THEN
            LOGON(un, pw||'@'||cs, FALSE);
            IF FORM_SUCCESS THEN            /* Successful logon */
               connected := TRUE;
            END IF;
         END IF;
         WHILE connected = FALSE and tries > 0 LOOP
            upc := un||pw||cs;
            LOGON_SCREEN;
            get_connect_info;
            IF upc = un||pw||cs THEN
               EXIT;
            END IF;
            LOGON(un, pw||'@'||cs, FALSE);
            IF FORM_SUCCESS THEN            /* Successful logon */
               connected := TRUE;
            END IF;
            tries := tries - 1;
         END LOOP;
         IF NOT connected THEN
            RAISE FORM_TRIGGER_FAILURE;
         END IF;
      END;

Note that the GET_APPLICATION_PROPERTY(CONNECT_STRING) will not work
in versions prior to 4.0.13 of Oracle Forms.  In prior versions, the
connect string is part of the password.

Small deviations from the default connect behavior can be accomplished
by modifying this code:

     *  To allow more or fewer logon attempts, increase the initial value of
        the counter variable, tries.

     *  To default the connect string, change the calls to LOGON from:
             LOGON(un, pw||'@'||cs, FALSE);
        to use a hard-coded connect string:
             LOGON(un, pw||'@<connect string>', FALSE);

     *  These lines can also be modified to hardcode username or password.

Hiding the Logon Information
============================
For security reasons, many customers do not want their users to be
able to access the database except through the forms.  One way to do
this is to have the form handle connecting to the database, which
keeps passwords away from the users.  In V7, the best way to do this
is to have the form set role to a privileged role.  However, a quick
and dirty way to do it is to have the form connect to a privileged,
secret ORACLE account.

The following On-Logon trigger establishes a connection using
hard-coded values for username and password.  Users will be able to
connect to the database without knowing the account or password:

   On-Logon (Form Level)
      LOGON('SCOTT','TIGER@T:MYHOST:V716');

Deferring Logon
===============
Connection can be deferred until later in the Forms processing.

   On-Logon (Form level)
      DECLARE
         un CHAR(30);
         pw CHAR(30);
         cs CHAR(30);
      BEGIN
         DEFAULT_VALUE('N','global.logon_now');
         IF :global.logon_now = 'Y' THEN
            LOGON_SCREEN;
            un := GET_APPLICATION_PROPERTY(USERNAME);
            pw := GET_APPLICATION_PROPERTY(PASSWORD);
            cs := GET_APPLICATION_PROPERTY(CONNECT_STRING);
            LOGON(un, pw||'@'||cs);
         END IF;
      END;

When the form starts up, it will not try to log on since the flag
logon_now will be defaulted to N.  When you do wish to log onto the
database, use the syntax:

    :global.logon_now := 'Y';
    LOGON(NULL, NULL);

This sets the flag to Y and causes the On-Logon trigger to fire, so
the form connects to the database.

Customizing the Logon Screen
============================
The built-in LOGON_SCREEN calls up the default Forms logon screen to
capture the username, password, and connect string.  However, you can
also use a customized logon screen.  The following tutorial creates a
form which can be used as a replacement logon screen from any form.
NOTE: Coordinate System is assumed to be pixel.

1.  Create a new forms module and change only the following properties:
       Name:         LOGON
       Title:        LOGON          (v4.5)

2.  Modify only the following properties for WINDOW0
    (v4.0, Create this window):
       Name:         LOGON_WINDOW
       Width:        126
       Height:       108
       Title:        Logon
       Style:        Dialog
       Modal:        TRUE
       Fixed Size:   TRUE
       Iconifiable:  FALSE
       Inherit Menu: FALSE
       Zoomable:     FALSE

3.  Create a new canvas (v4.0, Modify CANVAS0) and modify only the following
    properties:
       Name:         LOGON_CANVAS
       Window:       LOGON_WINDOW
       Width:        126
       Height:       108

4.  Modify only the following properties for LOGON_WINDOW:
       View:         LOGON_CANVAS

5.  Create a new block and modify only the following properties:
       Block Name:   LOGON_BLOCK

6.  Create three text items on canvas LOGON_CANVAS for block LOGON_BLOCK
    with properties as follows:
       Name:         USERNAME
       X Position:   12
       Y Position:   8
       Width:        102
       Height:       18

       Name:         PASSWORD
       X Position:   12
       Y Position:   31
       Width:        102
       Height:       18
       Secure:       TRUE

       Name:         CONNECT
       X Position:   12
       Y Position:   54
       Width:        102
       Height:       18

7.  Create two push buttons on canvas LOGON_CANVAS for block LOGON_BLOCK
    with properties as follows:
       Name:           LOGON
       X Position:     12
       Y Position:     84
       Width:          52
       Height:         18
       Label:          Logon
       Mouse Navigate: FALSE
       Default Button: TRUE

       Name:           CANCEL
       X Position:     72
       Y Position:     84
       Width:          52
       Height:         18
       Label:          Cancel
       Mouse Navigate: FALSE

8.  Code the following program units:

       PROCEDURE leave(status BOOLEAN DEFAULT TRUE) IS
       BEGIN
          IF status THEN
             :global.logged_on := 'TRUE';
          ELSE
             :global.logged_on := 'FALSE';
          END IF;
          EXIT_FORM;
       END;

       PROCEDURE initialize_form IS
          un VARCHAR2(30) := GET_APPLICATION_PROPERTY(USERNAME);
          pw VARCHAR2(30) := GET_APPLICATION_PROPERTY(PASSWORD);
          cs VARCHAR2(30) := GET_APPLICATION_PROPERTY(CONNECT_STRING);
       BEGIN
          DEFAULT_VALUE('3', 'global.logon_tries');
          DEFAULT_VALUE(un, 'global.username');
          DEFAULT_VALUE(pw, 'global.password');
          DEFAULT_VALUE(cs, 'global.connect_string');
          :logon_block.username := :global.username;
          :logon_block.password := :global.password;
          :logon_block.connect  := :global.connect_string;
       END;

       FUNCTION connect_to RETURN BOOLEAN IS
       BEGIN
          IF :logon_block.username IS NULL THEN
             BELL;
          END IF;
          LOGON(:logon_block.username,
                :logon_block.password||'@'||:logon_block.connect, FALSE);
          IF FORM_SUCCESS THEN
             RETURN TRUE;
          ELSE
             RETURN FALSE;
          END IF;
       END;

9.  Code the following triggers:

    On-Logon (Form Level)
       LOGON(:logon_block.username,
             :logon_block.password||'@'||:logon_block.connect,
             FALSE);

    When-New-Form-Instance (Form Level)
       initialize_form;

    When-Button-Pressed (Item Level, on LOGON_BLOCK.CANCEL)
       leave(FALSE);

    When-Button-Pressed (Item Level, on LOGON_BLOCK.LOGON)
       BEGIN
         IF connect_to THEN
            leave(TRUE);
         END IF;
         :global.logon_tries := TO_NUMBER(:global.logon_tries) - 1;
         IF TO_NUMBER(:global.logon_tries) = '0' THEN
            leave(FALSE);
         END IF;
      END;

    When-Window-Activated (Form Level)
       DECLARE
         screen_height  NUMBER;
         screen_width   NUMBER;
         window_height  NUMBER;
         window_width   NUMBER;
       BEGIN
         IF :SYSTEM.EVENT_WINDOW = 'LOGON_WINDOW' THEN
            screen_height := GET_APPLICATION_PROPERTY(DISPLAY_HEIGHT);
            screen_width := GET_APPLICATION_PROPERTY(DISPLAY_WIDTH);
            window_height := GET_WINDOW_PROPERTY(:SYSTEM.EVENT_WINDOW, HEIGHT);
            window_width := GET_WINDOW_PROPERTY(:SYSTEM.EVENT_WINDOW, WIDTH);
            SET_WINDOW_PROPERTY('LOGON_WINDOW', X_POS,
                               (screen_width - window_width)/2);
            SET_WINDOW_PROPERTY('LOGON_WINDOW', Y_POS,
                               screen_height/2 - window_height);
         END IF;
       END;

10.  Generate and save this form.

11.  Create a new form.  This form is an example of how to use the
     logon form that has just been created.

12.  Create a default block, giving this form some items.

13.  Code the On-Logon trigger as follows:

     On-Logon (Form Level)
        CALL_FORM('logon', NO_HIDE);
        IF :global.logged_on != 'TRUE' THEN
           RAISE FORM_TRIGGER_FAILURE;
        END IF;

This will complete the coding for the main form.  When the form now
requires a connection to the database, it will use this customized
logon screen instead of the Forms default one.