Windows ショートカット作成VBスクリプト

全員のデスクトップのショートカットを揃えたほうが電話でサポートしやすいね、ということで。
VBスクリプトを使ってショートカット作成スクリプトを作ってみた。

使い方は、こんな感じ。

C:\>create-shortcuts.vbs shortcut.conf

create-shortcuts.vbs

'#####################################################
' ショートカット作成スクリプト
' 設定ファイル複数受付版
'#####################################################
Const FOR_READING = 1
Const COL_FOLDER = 0
Const COL_SUB_FOLDER = 1
Const COL_TITLE = 2
Const COL_PATH = 3
Const COL_WORK = 4

Set objArgs = WScript.Arguments
'Wscript.Echo objArgs(0)
'Wscript.Echo objArgs.length

For arg_index = 0 to objArgs.length-1

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile(objArgs(arg_index), FOR_READING)

Do Until objTextFile.AtEndOfStream
  strNextLine = objTextFile.Readline
  if strNextLine <> "" then
    conf = Split(strNextLine , ",")
    if conf(COL_FOLDER) <> "" then
        Set Shell = CreateObject("WScript.Shell")
        CreatePath = Shell.SpecialFolders(conf(COL_FOLDER))
        if CreatePath = "" then CreatePath = conf(COL_FOLDER)
        if conf(COL_SUB_FOLDER) <> "" then
          CreatePath = CreatePath & "\" & conf(COL_SUB_FOLDER)
          if not objFSO.FolderExists(CreatePath) then
          	objFSO.CreateFolder(CreatePath)
          end if
        end if
        Set link = Shell.CreateShortcut(CreatePath & "\" & conf(COL_TITLE) &".lnk")
        link.Description = conf(COL_TITLE)
        link.HotKey = ""
        link.IconLocation = conf(COL_PATH)
        link.TargetPath = conf(COL_PATH)
        '通常のウインドウ
        link.WindowStyle = 1
        link.WorkingDirectory = conf(COL_WORK)
        args = ""
        For i = COL_WORK+1 to Ubound(conf)
          args = args & " " & conf(i)
        Next
        link.Arguments = args
        ret = link.Save

'デバッグ情報
'        Wscript.Echo "タイトル:" & conf(0)
'        Wscript.Echo "パス:" & conf(1)
'        Wscript.Echo "作業ディレクトリ:" & conf(2)
'        Wscript.Echo "引数:" & args
'        Wscript.Echo ret
    end if
  end if
Loop
Next

shortcut.conf

,********************************************
, カンマで始まる行はコメント行
,********************************************

,カンマで区切って、作成場所、タイトル,パス,作業ディレクトリ,引数1,引数2,引数3,...の順に書いておくと
,作成場所(デスクトップなど)にショートカットを作る

,作成場所に指定できるのは次のものだけ
, AllUsersDesktop
, AllUsersStartMenu
, AllUsersPrograms
, AllUsersStartup
, Desktop
, Favorites
, Fonts
, MyDocuments
, NetHood
, PrintHood
, Programs
, Recent
, SendTo
, StartMenu
, Startup
, Templates

,****************************************************************
, ここからが実際のデータ
,****************************************************************
Programs,,Excel,C:\Program Files\Microsoft Office\Office11\excel.exe,H:\,
Programs,,Word,C:\Program Files\Microsoft Office\Office11\winword.exe,H:\,
Programs,,PowerPoint,C:\Program Files\Microsoft Office\Office11\powerpnt.exe,H:\,
Programs,,Visio,C:\Program Files\Microsoft Office\Visio10\visio.exe,H:\,
Programs,,Access,C:\Program Files\Microsoft Office\Office11\msaccess.exe,H:\,

Desktop,,Excel,C:\Program Files\Microsoft Office\Office11\excel.exe,H:\,
Desktop,,Word,C:\Program Files\Microsoft Office\Office11\winword.exe,H:\,
Desktop,,PowerPoint,C:\Program Files\Microsoft Office\Office11\powerpnt.exe,H:\,
Desktop,,Visio,C:\Program Files\Microsoft Office\Visio10\visio.exe,H:\,
Desktop,,Access,C:\Program Files\Microsoft Office\Office11\msaccess.exe,H:\,

ActiveDirectoryのLDAP認証もどき

python-ldapを使ってみた。

ついでに、以前から試そうと思って手をつけていなかった、ActiveDirectoryのLDAP認証も。試しに、bindしてみるだけ。平文でパスワードが流れるのでこのままではちょっと使えない。

#!/usr/bin/env python
# -*- coding: utf-8-*-
# python-ldapを使ってActiveDirectoryで認証してみる
# http://python-ldap.sourceforge.net/

def ADAuth(username,password,host,port=389):
    """ActiveDirectoryのドメイコントローラにユーザ名とパスワードでbindしてみる。
    bindできれば認証OK。認証NGなら例外が起きる。
    """
    import ldap
    url = "ldap://%s:%d" % (host,port)
    l = ldap.initialize(url)
    l.simple_bind_s(username,password)
    l.unbind_s()

if __name__=='__main__':
    if len(sys.argv)<3:
        print "Usage: %s username password" % (sys.argv[0])
    else:
        try:
            userid = sys.argv[1]
            password = sys.argv[2]
            ADAuth(userid,password,"adserver.example.com")
            print "OK"
        except:
            print "NG"

Gist:227565

Pythonで3桁区切りのカンマ挿入


str.format()でいけるようになりました。locale使うよりこっちがお手軽でよい場合が多いでしょう。
http://docs.python.jp/2/whatsnew/2.7.html#pep-378-format-specifier-for-thousands-separator

PHPでいうところのnumber_formatのように、3桁毎に位取りのカンマを入れる方法はどうするの?ってことで。

いろいろ探してみたところ、これがよさそう。

>>> import locale
>>> locale.setlocale(locale.LC_NUMERIC, 'ja_JP')
'ja_JP'
>>> locale.format('%d', 10000, True)
'10,000'
>>> locale.format('%.2f', 10000.00, True)
'10,000.00'
>>> locale.format('%.2f', 9999.999, True)
'10,000.00'
>>>

Oracle PL/SQLとUNIXタイムスタンプ

Oracleのdate型とUNIXタイムスタンプを相互に変換するPL/SQL関数が必要になった。
作ってみた。

create or replace function to_unix_timestamp(dt date) return number is
begin
    return (dt - to_date('1970-01-01','YYYY-MM-DD')) * 86400;
end;
/
create or replace function from_unix_timestamp(ts number) return date is
begin
    return to_date(trunc(ts / 86400, 0) + 2440588, 'J') + (mod(ts, 86400) / 86400);
end;
/
select to_unix_timestamp(sysdate) from dual;
select to_char(from_unix_timestamp(to_unix_timestamp(sysdate)),'YYYY-MM-DD HH24:MI:SS') from dual;

消費税を計算するOracle PL/SQLパッケージ

消費税込み金額を計算したり、税抜き金額を計算したりするPL/SQLパッケージ。

消費税率が変わったらTAX_CALENDARという名前のテーブルに税率を追加すればいい。

これで消費税が上がっても大丈夫。10%でも20%でも平気。どんとこい。

TAX_RATE2は、テーブルを使わずに、FUNCTION内で日付とレートをハードコードして判断している。税率が変わったら書き直さないといけない。税率変わるたびにメンテナンス=ソース変更とリコンパイルが必要だけれど、まあ、運用環境によってはこっちがいい場合も多いか。シンプルだし速いはず。

/*
|| 消費税率のカレンダーテーブル
*/
DROP TABLE TAX_CALENDAR;
/
-- TAX CALENDAR TABLE
CREATE TABLE TAX_CALENDAR (
  DtS date NOT NULL,
  DtE date NOT NULL,
  TAX number(3,2)
);
-- TAX TABLE
ALTER TABLE TAX_CALENDAR ADD CONSTRAINT DISP_TAX_CALENDAR_PK PRIMARY KEY (DtS,DtE);
/
/*
|| TAX_CALENDAR INSERTION
*/
DELETE FROM TAX_CALENDAR;
INSERT INTO TAX_CALENDAR(DtS,DtE,Tax) VALUES(to_date('1900-01-01'),to_date('1989-04-01'),0.000);
INSERT INTO TAX_CALENDAR(DtS,DtE,Tax) VALUES(to_date('1989-04-01'),to_date('1997-04-01'),0.03);
INSERT INTO TAX_CALENDAR(DtS,DtE,Tax) VALUES(to_date('1997-04-01'),to_date('2999-04-01'),0.05);


CREATE OR REPLACE PACKAGE TAX_PKG AS
  -- 日付で消費税率を返す
  FUNCTION TAX_RATE(i_date IN date DEFAULT SYSDATE) RETURN NUMBER;
  -- 日付と金額で消費税額を返す
  FUNCTION TAX(i_price IN NUMBER,i_date IN date DEFAULT SYSDATE) RETURN NUMBER;
  -- 日付と金額で税込金額を返す
  FUNCTION INCLUDE_TAX(i_price IN NUMBER,i_date IN date DEFAULT SYSDATE) RETURN NUMBER;
  PRAGMA RESTRICT_REFERENCES(TAX_RATE,WNDS);
  PRAGMA RESTRICT_REFERENCES(TAX,WNDS);
  PRAGMA RESTRICT_REFERENCES(INCLUDE_TAX,WNDS);
END TAX_PKG;
/

CREATE OR REPLACE PACKAGE BODY TAX_PKG AS
    /*
    || 日付で消費税率を返す
    ||  TAX_CALENDARテーブルを参照する
    */
    FUNCTION TAX_RATE(i_date IN date DEFAULT SYSDATE) RETURN NUMBER
    IS
    ATax number;
    BEGIN
        SELECT TAX INTO ATAX FROM TAX_CALENDAR WHERE i_date >= DtS AND i_date < DtE;
        RETURN ATAX;
    END;
    /*
    || 日付で消費税率を返す
    */
    FUNCTION TAX_RATE2(i_date IN date DEFAULT SYSDATE) RETURN NUMBER
    IS
    BEGIN
        IF i_date < to_date('89-04-01') THEN
            RETURN 0.00;
        ELSIF i_date < to_date('97-04-01') THEN
            RETURN 0.03;
        ELSE
            RETURN 0.05; --現状
        END IF;
    END;
    -------------------------------------------------------
    -- 日付と金額で消費税額を返す
    -------------------------------------------------------
    FUNCTION TAX(i_price IN NUMBER, i_date IN date DEFAULT SYSDATE) RETURN NUMBER
    IS
    BEGIN
        RETURN ROUND(i_price * TAX_RATE(i_date));
    END;
    -------------------------------------------------------
    -- 日付と金額で税込金額を返す
    -------------------------------------------------------
    FUNCTION INCLUDE_TAX(i_price IN NUMBER, i_date IN date DEFAULT SYSDATE) RETURN NUMBER
    IS
    BEGIN
        RETURN ROUND(i_price + (i_price * TAX_RATE(i_date)));
    END;
END TAX_PKG;
/


-------------------------------------------------------
-- 消費税計算のテスト用
-------------------------------------------------------
select tax_pkg.tax_rate('89-03-31'),
 tax_pkg.tax_rate('89-04-01'),
 tax_pkg.tax_rate('97-03-31'),
 tax_pkg.tax_rate('97-04-01'),
 tax_pkg.tax_rate(SYSDATE)
from dual;

select tax_pkg.tax(101,'89-03-31'),
 tax_pkg.tax(101,'89-04-01'),
 tax_pkg.tax(101,'97-03-31'),
 tax_pkg.tax(101,'97-04-01'),
 tax_pkg.tax(101,SYSDATE)
from dual;

select tax_pkg.include_tax(101,'89-03-31'),
 tax_pkg.include_tax(101,'89-04-01'),
 tax_pkg.include_tax(101,'97-03-31'),
 tax_pkg.include_tax(101,'97-04-01'),
 tax_pkg.include_tax(101,SYSDATE)
from dual;

ユーザ管理をするOracle PL/SQLパッケージ

ユーザIDやパスワードは、OracleのDBMS_OBFUSCATION_TOOLKITパッケージを使って暗号化して保管するPL/SQLパッケージ。DBMS_OBFUSCATION_TOOLKITを使っているので、Oracle9i以降が必要(たぶん)。

ユーザ情報管理機能の必要なアプリケーションで使うと便利かもしれない。

もう使ってはいけないとどこかで読んだような気もするmd5でハッシュをとっている部分は、簡単な変更で入れ替えることもできるはず。

このパッケージを使うことで、アプリケーションからは暗号化/復号化の処理、テーブルの列構成の詳細を隠蔽することができるはず。

小道具というにはちょっと大きいかも。

http://gist.github.com/233572

/**
* ユーザ認証管理パッケージ
* テーブルUSER_AUTHとパッケージAUTH_PKGで構成される。
* ユーザIDとパスワードはMD5ダイジェストとして格納される。
* Oracle9i以降専用!!
*
* ユーザIDの管理(あるユーザIDは誰か?など)は当パッケージを利用するシステムの責任
* ユーザIDを登録(REGIST_USER)、削除(DROP)、パスワード認証(AUTHENTICATE)などを管理する
*
* クラス:ユーザIDのクラス。ユーザIDはクラス内でユニークである必要がある。
* ユーザID:何文字でもいい。内部ではMD5のハッシュで管理している。クラス内でユニークとなること。
* パスワード:何文字でもいい。内部ではMD5のハッシュで管理している

* 複数のクラスを管理する場合は、SET_USERCLASSを呼び出してから他の操作をすること。
* USERCLASS()で現在どのクラスを使っているかを知ることができる。
* 最初にAUTH_PKG.SET_USERCLASS(ユーザクラス)を呼び出して使うクラスの設定を初期化する。
* この初期化をしないと、クラスとして「DEFAULT」が設定される。
* 初期化しないで使う場合は、全関数でユーザクラスを最初の引数に指定する。
*
* RETURN_CODE_TRUEとRETURN_CODE_FALSEはFUNCTIONが返す論理値に割り当てる文字列を指定する。
* RETURN_CODE_TRUEにはTRUEの時に返す文字列。デフォルトは'Y'。
* RETURN_CODE_FALSEにはFASEの時に返す文字列。デフォルトは'N'。
*
* テーブル名
* USER_AUTH
*
* 順序名
* SEQ_USER_AUTH_ID
*
*/



/******************************************************************
 ユーザ認証管理パッケージ用の認証テーブル USER_AUTHの作成
*******************************************************************/
DROP SEQUENCE SEQ_USER_AUTH_ID;
CREATE SEQUENCE SEQ_USER_AUTH_ID;

DROP TABLE USER_AUTH;
CREATE TABLE USER_AUTH(
 AuthId number(9,0) NOT NULL,
 UserClass varchar2(10) NOT NULL,
 UserId char(32) NOT NULL,
 Password char(32) NOT NULL,
 PasswordChanged date DEFAULT SYSDATE,
 Updated date DEFAULT SYSDATE,
 Created date NOT NULL
);
COMMENT ON TABLE USER_AUTH IS 'ユーザ認証システム:認証テーブル';
COMMENT ON COLUMN USER_AUTH.AuthID IS '認証ID AUTH_ID_SEQで発番された連番';
COMMENT ON COLUMN USER_AUTH.UserClass IS 'ユーザIDの属しているクラス';
COMMENT ON COLUMN USER_AUTH.UserID IS 'ユーザID:ユーザ入力値のMD5メッセージダイジェスト。';
COMMENT ON COLUMN USER_AUTH.Password IS 'パスワード:ユーザ入力値のMD5メッセージダイジェスト';
COMMENT ON COLUMN USER_AUTH.PasswordChanged IS '最後にパスワードを変更した日時';
COMMENT ON COLUMN USER_AUTH.Updated IS '更新日時';
COMMENT ON COLUMN USER_AUTH.Created IS '作成日時';

CREATE UNIQUE INDEX USER_AUTH_USERID ON USER_AUTH(UserClass,UserID);
ALTER TABLE USER_AUTH ADD CONSTRAINT USER_AUTH_PK PRIMARY KEY (AuthID);


/******************************************************************
 AUTH_PKG本体の作成
*******************************************************************/
CREATE OR REPLACE PACKAGE AUTH_PKG AS
 --グローバル変数定義

 --TRUE/FALSEやOK/NGやYES/NOに変更してもいい
 RETURN_CODE_TRUE VARCHAR2(10) := 'Y';
 RETURN_CODE_FALSE VARCHAR2(10) := 'N';

 --USERCLASSを設定しない場合のデフォルトユーザクラス
 DEFAULT_USERCLASS CONSTANT VARCHAR2(10) := 'DEFAULT';

 --初期登録でパスワードを指定しなかった場合にデフォルトで指定するパスワード
 DEFAULT_PASSWORD CONSTANT VARCHAR2(32) := 'changeOnInstall';

 -- パッケージのユーザクラスをセットする
  PROCEDURE SET_USERCLASS(i_userclass IN VARCHAR2);

 -- 設定されているユーザクラスを返す
  FUNCTION USERCLASS RETURN VARCHAR2;

 --パスワード変更
  PROCEDURE CHANGE_PASSWORD(i_userclass IN VARCHAR2, i_userid IN VARCHAR2, i_password IN VARCHAR2);
  PROCEDURE CHANGE_PASSWORD(i_userid IN VARCHAR2, i_password IN VARCHAR2);

 --ユーザ完全削除
  PROCEDURE DROP_USER(i_userclass IN VARCHAR2, i_userid IN VARCHAR2);
  PROCEDURE DROP_USER(i_userid IN VARCHAR2);

 --ユーザ登録
  --パスワードを指定しないとデフォルト値が設定される
  PROCEDURE REGIST_USER(i_userclass IN VARCHAR2, i_userid IN VARCHAR2, i_password IN VARCHAR2);
  PROCEDURE REGIST_USER(i_userid IN VARCHAR2, i_password IN VARCHAR2);

 --ユーザの存在チェック
  FUNCTION USER_EXISTS(i_userclass IN VARCHAR2, i_userid IN VARCHAR2) RETURN CHAR;
  FUNCTION USER_EXISTS(i_userid IN VARCHAR2) RETURN CHAR;

 --認証(パスワードチェック)してOKならRETURN_CODE_TRUEを返す。失敗したらRETURN_CODE_FALSEを返す
  FUNCTION AUTHENTICATE(i_userid IN VARCHAR2, i_password IN VARCHAR2) RETURN VARCHAR2;
  FUNCTION AUTHENTICATE(i_userclass IN VARCHAR2, i_userid IN VARCHAR2, i_password IN VARCHAR2) RETURN VARCHAR2;

 --最後にパスワードを変更した日時を返す
  FUNCTION PASSWORD_CHANGED(i_userclass IN VARCHAR2, i_userid IN VARCHAR2) RETURN DATE;
  FUNCTION PASSWORD_CHANGED(i_userid IN VARCHAR2) RETURN DATE;

 --最後にパスワードを変更した日時が有効な日数(i_days)を過ぎていたらRETURN_CODE_TRUEを返す
  FUNCTION PASSWORD_EXPIRED(i_userclass IN VARCHAR2, i_userid IN VARCHAR2, i_days IN NUMBER) RETURN CHAR;
  FUNCTION PASSWORD_EXPIRED(i_userid IN VARCHAR2, i_days IN NUMBER) RETURN CHAR;

 --指定した文字数のランダムな文字列を返す。初期パスワードの生成に。
  FUNCTION RANDOM_STRING(i_string_length IN NUMBER DEFAULT 6) RETURN VARCHAR2;

 --MD5 基本的には内部利用を想定しているけれど、別に外で使っても良い
  FUNCTION MD5(input_string IN VARCHAR2) RETURN VARCHAR2;

 --暗号化した文字列を返す 現バージョンはMD5を使った1方向だけに対応。
  FUNCTION ENCRYPT(input_string IN VARCHAR2, ENCRYPT_METHOD IN VARCHAR2 DEFAULT 'MD5') RETURN VARCHAR2;
END AUTH_PKG;

/


CREATE OR REPLACE PACKAGE BODY AUTH_PKG AS
--パッケージローカルのセッション内変数
CURRENT_USERCLASS VARCHAR2(10) := DEFAULT_USERCLASS;
SEED_COUNTER number := 1;

----------------------------------------------------------
-- md5ダイジェストを得るためのストアードファンクション
-- USER_AUTHテーブルのpasswordフィールドにはmd5ダイジェストを記録する
----------------------------------------------------------
FUNCTION MD5(input_string IN VARCHAR2) RETURN VARCHAR2
IS
hex_digest varchar2(32);
digest varchar2(16);
BEGIN
 digest := DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => input_string);
 SELECT Lower(RAWTOHEX(digest)) INTO hex_digest FROM dual;
 RETURN hex_digest;
END;

----------------------------------------------------------
-- 受け取った文字列を暗号化して返す
----------------------------------------------------------
FUNCTION ENCRYPT(input_string IN VARCHAR2, ENCRYPT_METHOD IN VARCHAR2 DEFAULT 'MD5') RETURN VARCHAR2
IS
BEGIN
 IF ENCRYPT_METHOD = 'MD5' THEN
    RETURN MD5(input_string);
 ELSE
  RAISE_APPLICATION_ERROR(-20003,'暗号化方法' || ENCRYPT_METHOD || 'が私には理解できません。');
 END IF;
END;

----------------------------------------------------------
-- P 初期化する
----------------------------------------------------------
PROCEDURE SET_USERCLASS( i_userclass IN VARCHAR2)
IS
BEGIN
 CURRENT_USERCLASS := i_userclass;
END;

----------------------------------------------------------
-- F CURRENT_USERIDを返す
----------------------------------------------------------
FUNCTION USERCLASS RETURN VARCHAR2
IS
BEGIN
 RETURN CURRENT_USERCLASS;
END;


----------------------------------------------------------
-- P CHANGE_PASSWORD
----------------------------------------------------------
PROCEDURE CHANGE_PASSWORD
 ( i_userclass IN VARCHAR2,
   i_userid IN VARCHAR2,
   i_password IN VARCHAR2)
IS
 ret_val CHAR(1) := RETURN_CODE_TRUE;
BEGIN
 ret_val := USER_EXISTS(i_userclass, i_userid);
 IF ret_val = RETURN_CODE_TRUE THEN
   UPDATE USER_AUTH
    SET
     password = ENCRYPT(i_password),
     PasswordChanged=SYSDATE,
     Updated=SYSDATE
    WHERE userclass = i_userclass
     AND userid = ENCRYPT(i_userid);
 END IF;
END;


PROCEDURE CHANGE_PASSWORD
 ( i_userid IN VARCHAR2,
   i_password IN VARCHAR2)
IS
BEGIN
 CHANGE_PASSWORD(CURRENT_USERCLASS, i_userid, i_password);
END;

----------------------------------------------------------
-- P DROP_USER 完全にレコードを削除する
----------------------------------------------------------
PROCEDURE DROP_USER (i_userclass IN VARCHAR2, i_userid IN VARCHAR2)
IS
BEGIN
 DELETE USER_AUTH
  WHERE userclass = i_userclass
   AND userid = ENCRYPT(i_userid);
END;

PROCEDURE DROP_USER (i_userid IN VARCHAR2)
IS
BEGIN
 DROP_USER(CURRENT_USERCLASS, i_userid);
END;


----------------------------------------------------------
-- P REGIST_USER
----------------------------------------------------------
PROCEDURE REGIST_USER(i_userclass IN VARCHAR2, i_userid IN VARCHAR2, i_password IN VARCHAR2)
IS
BEGIN
 IF USER_EXISTS(i_userclass, i_userid)=RETURN_CODE_TRUE THEN
  RAISE_APPLICATION_ERROR(-20002,'ご指定のユーザ' || i_userid || 'は既に存在しています。');
 ELSE
  INSERT INTO USER_AUTH(authid,userclass,userid,password,updated,created)
   VALUES(SEQ_USER_AUTH_ID.NEXTVAL,i_userclass,ENCRYPT(i_userid),ENCRYPT(i_password),SYSDATE,SYSDATE);
 END IF;
END;

PROCEDURE REGIST_USER( i_userid IN VARCHAR2, i_password IN VARCHAR2)
IS
BEGIN
 REGIST_USER(CURRENT_USERCLASS, i_userid, i_password);
END;

----------------------------------------------------------
-- F USER_EXISTS ユーザが存在したらRETURN_CODE_TRUE、存在しなければRETURN_CODE_FALSEを返す
----------------------------------------------------------
FUNCTION USER_EXISTS(i_userclass IN VARCHAR2, i_userid IN VARCHAR2)
RETURN CHAR
IS
 r number;
BEGIN
 SELECT COUNT(*) INTO r
  FROM USER_AUTH
  WHERE userclass=i_userclass
   AND userid = ENCRYPT(i_userid);
 IF r > 0 THEN
  RETURN RETURN_CODE_TRUE;
 ELSE
  RETURN RETURN_CODE_FALSE;
 END IF;
END;

FUNCTION USER_EXISTS( i_userid IN VARCHAR2)
RETURN CHAR
IS
BEGIN
 RETURN USER_EXISTS(CURRENT_USERCLASS, i_userid);
END;

----------------------------------------------------------
-- F AUTH
----------------------------------------------------------
--認証(パスワードチェック)してOKならRETURN_CODE_TRUEを返す。失敗したらRETURN_CODE_FALSEを返す
FUNCTION AUTHENTICATE(
   i_userclass IN VARCHAR2,
   i_userid IN VARCHAR2,
   i_password IN VARCHAR2
   ) RETURN VARCHAR2
IS
 r number;
BEGIN
  SELECT COUNT(*) INTO r
  FROM USER_AUTH
  WHERE userclass=i_userclass
   AND userid = ENCRYPT(i_userid)
   AND password = ENCRYPT(i_password);
 IF r > 0 THEN
  RETURN RETURN_CODE_TRUE;
 ELSE
  RETURN RETURN_CODE_FALSE;
 END IF;
END;

--認証(パスワードチェック)してOKならRETURN_CODE_TRUEを返す。失敗したらRETURN_CODE_FALSEを返す
FUNCTION AUTHENTICATE(
   i_userid IN VARCHAR2,
   i_password IN VARCHAR2
   ) RETURN VARCHAR2
IS
BEGIN
  RETURN AUTHENTICATE(CURRENT_USERCLASS, i_userid, i_password);
END;


----------------------------------------------------------
-- F PASSWORD
----------------------------------------------------------
--パスワードの変更日時を返す。
FUNCTION PASSWORD_CHANGED(
   i_userclass IN VARCHAR2,
   i_userid IN VARCHAR2
   ) RETURN DATE
IS
 r date;
BEGIN
  SELECT PasswordChanged INTO r
  FROM USER_AUTH
  WHERE userclass=i_userclass
   AND userid = ENCRYPT(i_userid);
  RETURN r;
END;

--パスワードの変更日時を返す。
FUNCTION PASSWORD_CHANGED(
   i_userid IN VARCHAR2
   ) RETURN DATE
IS
BEGIN
  RETURN PASSWORD_CHANGED(CURRENT_USERCLASS, i_userid);
END;

----------------------------------------------------------
-- F PASSWORD_EXPIRED
----------------------------------------------------------
--パスワードの有効期限が過ぎているかどうかをチェックしてRETURN_CODEを返す。
FUNCTION PASSWORD_EXPIRED(
   i_userclass IN VARCHAR2,
   i_userid IN VARCHAR2,
   i_days IN NUMBER
   ) RETURN CHAR
IS
 r date;
BEGIN
 SELECT PASSWORD_CHANGED(i_userclass,i_userid) + i_days INTO r FROM DUAL;
 IF r < SYSDATE THEN
  RETURN RETURN_CODE_TRUE;
 ELSE
  RETURN RETURN_CODE_FALSE;
 END IF;
END;

FUNCTION PASSWORD_EXPIRED(
   i_userid IN VARCHAR2,
   i_days IN NUMBER
   ) RETURN CHAR
IS
 r date;
BEGIN
  RETURN PASSWORD_EXPIRED(CURRENT_USERCLASS, i_userid);
END;


----------------------------------------------------------
-- F ランダムな文字列を返す
----------------------------------------------------------
FUNCTION RANDOM_STRING(i_string_length IN NUMBER DEFAULT 6) RETURN VARCHAR2
IS
seed number;
r char(32);
BEGIN
 seed := to_number(to_char(sysdate,'SSSSS')) + SEED_COUNTER;
 SEED_COUNTER := SEED_COUNTER + 1;
 dbms_random.initialize(seed);
 dbms_random.seed(seed);
 r := MD5(to_char(abs(dbms_random.random())));
 RETURN substr(r,-i_string_length,i_string_length);
END;

END AUTH_PKG;