#!/usr/local/bin/perl


##
## some configuration options
##

# if true, converts:
#    as-name: AS-xxxx
# to:
#    as-name: AS_xxxx  # '-' converted to '_' for RPSL compliance
my $CONVERT_AS_NAME = 1;

# if true, converts invalid mnter and mnt-by:
#    mntner: RS-whatever
# to:
#    mntner: RS-whatever  # ERROR: invalid RPSL maintainer name
my $WARN_INVALID_MNTNER = 1;

# if true, uses RIPE-NCC-AN-MNT for aut-num maintainer rather than RIPE-NCC-NONE
#    mntner: RIPE-NCC-AN-MNT  # WARNING: maintainer added to protect object
my $PROTECT_AUT_NUM = 1;

# if true, converts multiple attributes into single, line-continued attribute
my $USE_MULTILINE = 0;

# fix missing attributes
my $FIX_MISSING = 1;

# remove empty attributes
my $REMOVE_EMPTY = 1;


# Autogenerated block to include site configuration
# generated on Fri Feb 5 11:39:20 PST 1999
BEGIN {
  %::RIPEConfig = (
          VERSION => q#3.0.0a16#,
          LIBDIR => q#/home/bird/a16/lib#,
          DEFCONFIG => q#/home/bird/a16/etc/ripedb.config#,
          WHOISHOST => q#localhost#,
  );

  # Add library path unless running from source directory
  use FindBin;
  if ($FindBin::Bin =~ m#/src$#) {
    unshift @INC, $FindBin::Bin;
  } else {
    unshift @INC, $::RIPEConfig{LIBDIR};
  }
  # Select DBM package other then the default one
}

# End of autogenerated block


# $Id: ripe2rpsl,v 1.1 2001/09/13 11:04:09 andrei Exp $
# 

# Copyright (c) 1997,1998 by the University of Southern California
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by the University of Southern California, Information
# Sciences Institute. The name of the USC may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
# OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
# OR PERFORMANCE OF THIS SOFTWARE.

#
# Copyright (c) 1998, 1999 by Qwest Communications International
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by Qwest Communications International. The name of Qwest
# Communications International may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# Qwest Communications International DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL Qwest Communications International OR ANY OTHER 
# CONTRIBUTOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
# DAMAGES, WHETHER IN CONTRACT, TORT, OR OTHER FORM OF ACTION, ARISING 
# OUT OF OR IN CONNECTION WITH, THE USE OR PERFORMANCE OF THIS SOFTWARE.

#
#  Author(s): Cengiz Alaettinoglu <cengiz@isi.edu>
#  Author(s): David Kessens <david@Qwest.net>

# 1. convert ripe line continuations to rpsl style
#      A note on ripe 181: A line can be continued to the next line 
#      by repeating everything upto the policy expression.
#      E.g.
#      as-in: AS1 1 ANY AND NOT
#      as-in: AS1 1 AS1
#     
#      is equivalant to
#      as-in: AS1 1 ANY AND NOT AS1
# 2.

#
# changes:
#
# bugs: - extra newline added by beatifier
#       - mnt-by for anybody
#       - *em: nobody@nowhere.net bad hack

#
# start included stuff from the RPSL RIPE database for conversions and fixes
# of RIPE181 -> RPSL

use Socket;

#
# from Makefile

#
# modified and simplified logmessage routine 

sub logmessage {

    shift(@_);
    print STDERR @_, "\n";

}


#
# hardcoded from config file
local($AUTOBOX)='cengiz@isi.edu';
local($MAXATTRIBUTELENGTH)=12;
local(%OBJATSQ)=('cm', 'cm de cy au tc ac rm ny mb ch so ud',
'mt', 'mt de cy ac tc dt mn at rm ny mb ay rb ch so ud',
'ro', 'ro ad cy ph fx em tb ac tc nh rm rl ny mb ch so ud',
'dn', 'dn de cy rf ac tc zc ns sd di rm ny mb ml ch so ud',
'as', 'as de cy ms mr rm tc ac ny mb ch so ud',
'rs', 'rs de cy ms mr rm tc ac ny mb ch so ud',
'li', 'li de cy tx ac ah rm ny mb ch so ud',
'rt', 'rt de cy or wd mo ij co ab ag ec ho rm cn ct ny mb ch so av cl ud',
'in', 'in na de cy ac tc rz st rm ny mb ml ch so ud',
'dc', 'dc de cy ac td rp pl rm ny mb ch so ud',
'ir', 'ir az la if pe ac tc rm ny mb ch so ud',
'is', 'is or de lo cy pf ap tl cc rm rl ny mb ch so ud',
'pn', 'pn ad cy ph fx em nh rm rl ny mb ch so ud',
'am', 'am de cy al ny tc ac rm ny mb ch so ud',
'i6', 'i6 na de cy ac tc rz st rm ny mb ml ch so ud',
'an', 'an aa de cy mo ip ep df ac tc rm cn ct ny mb ch so av ae ai ao it io ud',
'kc', 'kc mh ow fp ce rm ny mb ch so ud');
local(%ATTR)=('rp-attribute', 'rp',
'mnt-lower', 'ml',
'change', 'ch',
'ipv6-site', 'is',
'local-as', 'la',
'prefix', 'pf',
'typedef', 'td',
'export-comps', 'ec',
'descr', 'de',
'author', 'ah',
'refer', 'rf',
'application', 'ap',
'e-mail', 'em',
'warning', 'uw',
'inet6num', 'i6',
'rf', 'rf',
'location', 'lo',
'zc', 'zc',
'rl', 'rl',
'rm', 'rm',
'ro', 'ro',
'rp', 'rp',
'cross-nfy', 'cn',
'rs', 'rs',
'default', 'df',
'rt', 'rt',
'cc', 'cc',
'origin', 'or',
'changed', 'ch',
'ch', 'ch',
'zone-c', 'zc',
'rz', 'rz',
'cl', 'cl',
'cm', 'cm',
'cn', 'cn',
'co', 'co',
'as-macro', 'am',
'aggr-mtd', 'ag',
'comm-list', 'cl',
'dictionary', 'dc',
'ct', 'ct',
'sd', 'sd',
'member-of', 'mo',
'cy', 'cy',
'localas', 'la',
'so', 'so',
'components', 'co',
'st', 'st',
'dc', 'dc',
'authority', 'au',
'de', 'de',
'network', 'in',
'df', 'df',
'la', 'la',
'aggr-bndry', 'ab',
'di', 'di',
'auth-num', 'an',
'dn', 'dn',
'mntner', 'mt',
'rev-srv', 'rz',
'remarks', 'rm',
'li', 'li',
'tb', 'tb',
'tc', 'tc',
'dt', 'dt',
'td', 'td',
'notify', 'ny',
'holes', 'ho',
'lo', 'lo',
'tl', 'tl',
'community', 'cm',
'ec', 'ec',
'mnt-nfy', 'mn',
'alias', 'az',
'tx', 'tx',
'mb', 'mb',
'em', 'em',
'ep', 'ep',
'mnt-by', 'mb',
'person', 'pn',
'deleted', 'ud',
'netnum', 'in',
'ml', 'ml',
'ud', 'ud',
'ue', 'ue',
'mn', 'mn',
'mo', 'mo',
'inject', 'ij',
'ex', 'ep',
'mr', 'mr',
'ms', 'ms',
'mt', 'mt',
'uo', 'uo',
'status', 'st',
'text', 'tx',
'address', 'ad',
'fax-no', 'fx',
'members', 'ms',
'uw', 'uw',
'peer', 'pe',
'route', 'rt',
'na', 'na',
'limerick', 'li',
'protocol', 'pl',
'dom-net', 'di',
'inet-rtr', 'ir',
'nh', 'nh',
'withdrawn', 'wd',
'interas-in', 'it',
'phone', 'ph',
'trouble', 'tb',
'fx', 'fx',
'nic-hdl', 'nh',
'override', 'uo',
'inetnum', 'in',
'ns', 'ns',
'remark', 'rm',
'aut-num', 'an',
'ny', 'ny',
'netname', 'na',
'gd', 'ny',
'guardian', 'ny',
'contact', 'cc',
'as-set', 'as',
'source', 'so',
'advisory', 'av',
'role', 'ro',
'delete', 'ud',
'country', 'cy',
'asname', 'aa',
'domain', 'dn',
'upd-to', 'dt',
'as-out', 'ao',
'interas-out', 'io',
'import', 'ip',
'wd', 'wd',
'i6', 'i6',
'or', 'or',
'export', 'ep',
'nserver', 'ns',
'mbrs-by-ref', 'mr',
'route-set', 'rs',
'email', 'em',
'error', 'ue',
'auth', 'at',
'url', 'rl',
'pe', 'pe',
'rev-svr', 'rz',
'pf', 'pf',
'ho', 'ho',
'sub-dom', 'sd',
'ph', 'ph',
'as-in', 'ai',
'admin-c', 'ac',
'pl', 'pl',
'pn', 'pn',
'*error*', 'ue',
'fax', 'fx',
'as-name', 'aa',
'aa', 'aa',
'ab', 'ab',
'ac', 'ac',
'ad', 'ad',
'ae', 'ae',
'cross-mnt', 'ct',
'ag', 'ag',
'hole', 'ho',
'ah', 'ah',
'ifaddr', 'if',
'ai', 'ai',
'as-exclude', 'ae',
'al', 'al',
'am', 'am',
'if', 'if',
'an', 'an',
'ao', 'ao',
'ap', 'ap',
'ij', 'ij',
'as', 'as',
'tech-c', 'tc',
'at', 'at',
'au', 'au',
'tunnel', 'tl',
'im', 'ip',
'in', 'in',
'av', 'av',
'io', 'io',
'ip', 'ip',
'ir', 'ir',
'az', 'az',
'is', 'is',
'it', 'it',
'as-list', 'al',
 'key-cert', 'kc',
 'kc', 'kc',
 'method', 'mh',
 'mh', 'mh',
 'owner', 'ow',
 'ow', 'ow',
 'fingerpr', 'fp',
 'fp', 'fp',
 'certif', 'ce',
 'ce','ce',
 'referral-by','rb',
 'auth-override','ay'
);

# 
# some non standard Merit stuff ...

$ATTR{"ne"}="ne";
$ATTR{"np"}="np";
$ATTR{"cp"}="cp";
$ATTR{"ri"}="ri";
$ATTR{"rx"}="rx";

# 
# 2-character abbreviation to RPSL name mapping
local(%ATTL)=('ms', 'members',
'mt', 'mntner',
'uo', 'override',
'uw', 'WARNING',
'na', 'netname',
'nh', 'nic-hdl',
'rf', 'refer',
'zc', 'zone-c',
'rl', 'url',
'fx', 'fax-no',
'rm', 'remarks',
'ro', 'role',
'ns', 'nserver',
'rp', 'rp-attribute',
'rs', 'route-set',
'rt', 'route',
'cc', 'contact',
'ny', 'notify',
'ch', 'changed',
'rz', 'rev-srv',
'cl', 'comm-list',
'cm', 'community',
'cn', 'cross-nfy',
'co', 'components',
'sd', 'sub-dom',
'ct', 'cross-mnt',
'wd', 'withdrawn',
'cy', 'country',
'i6', 'inet6num',
'or', 'origin',
'so', 'source',
'st', 'status',
'dc', 'dictionary',
'de', 'descr',
'df', 'default',
'di', 'dom-net',
'la', 'local-as',
'dn', 'domain',
'li', 'limerick',
'pe', 'peer',
'tb', 'trouble',
'pf', 'prefix',
'tc', 'tech-c',
'ho', 'holes',
'td', 'typedef',
'dt', 'upd-to',
'ph', 'phone',
'lo', 'location',
'pl', 'protocol',
'pn', 'person',
'tl', 'tunnel',
'aa', 'as-name',
'ab', 'aggr-bndry',
'ac', 'admin-c',
'ad', 'address',
'ae', 'as-exclude',
'ag', 'aggr-mtd',
'ec', 'export-comps',
'ah', 'author',
'ai', 'as-in',
'tx', 'text',
'al', 'as-list',
'am', 'as-macro',
'an', 'aut-num',
'if', 'ifaddr',
'mb', 'mnt-by',
'ao', 'as-out',
'ap', 'application',
'em', 'e-mail',
'ij', 'inject',
'as', 'as-set',
'ep', 'export',
'at', 'auth',
'au', 'authority',
'in', 'inetnum',
'av', 'advisory',
'io', 'interas-out',
'ml', 'mnt-lower',
'ip', 'import',
'ud', 'delete',
'ue', '*ERROR*',
'mn', 'mnt-nfy',
'ir', 'inet-rtr',
'az', 'alias',
'mo', 'member-of',
'is', 'ipv6-site',
'it', 'interas-in',
'mr', 'mbrs-by-ref',
 'kc','key-cert',
 'mh','method',
 'ow','owner',
 'fp','fingerpr', 
 'ce','certif',
 'ay','auth-override',
 'rb','referral-by'
);

#
#       The file 'defines.pl' is included here
#



#       $RCSfile: ripe2rpsl,v $
#       $Revision: 1.1 $
#       $Author: andrei $
#       $Date: 2001/09/13 11:04:09 $

# Original code is written by various authors

# Copyright (c) 1993, 1994, 1995, 1996, 1997  The TERENA Association
# Copyright (c) 1998                              RIPE NCC
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the author not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Copyright (c) 1997,1998 by the University of Southern California
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by the University of Southern California, Information
# Sciences Institute. The name of the USC may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
# OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
# OR PERFORMANCE OF THIS SOFTWARE.

#
# Copyright (c) 1998, 1999 by Qwest Communications International
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by Qwest Communications International. The name of Qwest
# Communications International may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# Qwest Communications International DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL Qwest Communications International OR ANY OTHER 
# CONTRIBUTOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
# DAMAGES, WHETHER IN CONTRACT, TORT, OR OTHER FORM OF ACTION, ARISING 
# OUT OF OR IN CONNECTION WITH, THE USE OR PERFORMANCE OF THIS SOFTWARE.

#
# Author(s): David Kessens <david@Qwest.net>


#$DEBUG=1;
$DEBUG=0;

$HELPREQUESTED=0;
$STOPUPDATING=0;
%RPSLCONVERSIONSOURCES=();
%RPSLCONVERSION=();

%NOTIFY=();
%FORWARD=();
%NOTIFYMAILS=();

%NOIPv4ROUTES=();
@NOIPv4NETS=();

%OVERRIDECREATION=();
%OVERRIDEMODIFY=();
%OVERRIDEDELETION=();
%ACLDEFINED=();


%TYPEDEFS=();
%PROTOCOLS=();
%METHODS=();

@DEFLOOK=();
@ALLLOOK=();

$LOADEDDICTIONARY="";

$OK             =       1;
$NOK            =       0;
$EOF            =       99;

$LOCK_SH = 1;
$LOCK_EX = 2;
$LOCK_NB = 4;
$LOCK_UN = 8;

# Return codes for when trying to modify the database
# with explanatory messages. These are used deep down in the code
# just before or during updates, like dbadd.pl and updatecheck.pl.

$E_EXIST         =      2;
$E_NOT_FOUND     =      3;
$E_MULT_MATCH    =      4;
$E_MISMATCH      =      5;
$E_NOOP          =      6;
$E_OLDER         =      7;
$E_AUTHFAIL      =      9;
$E_HIER_AUTHFAIL =     10;
$E_GENERAL       =     11;
$E_NOAUTOUPDATE  =     12;
$E_NOTNEW        =     13;
$E_STILLREFERENCED =   14;
$E_NOT_ORIGINAL  =     15;
$E_NO_MNTNERS_FOUND =  16;
$E_NO_TL_FOUND   =     17;
$E_NO_TL_CREATION =    18;
$E_HIER_NO_MNTNERS_FOUND = 19;

$MESSAGE[$E_EXIST]                 = "entry already exists";
$MESSAGE[$E_NOT_FOUND]             = "entry not found";
$MESSAGE[$E_MULT_MATCH]            = "don\'t know which object to update,\nmore matches found in the database";
$MESSAGE[$E_MISMATCH]              = "mismatch between update and original";
$MESSAGE[$E_NOOP]                  = "update results in NOOP";
$MESSAGE[$E_OLDER]                 = "update is older than original";
$MESSAGE[$E_AUTHFAIL]              = "authorisation failed, request forwarded to maintainer";
$MESSAGE[$E_HIER_AUTHFAIL]         = "hierarchical authorisation failed, request forwarded to maintainer\nof object directly above the to be updated object in the hierarchy";
$MESSAGE[$E_GENERAL]               = "";
$MESSAGE[$E_NOTNEW]                = "object already exists\n-\nthe database accepts only new objects\nand no changes to existing objects\nwhen the keyword \'new\' is used in the\n\'Subject:\' line of your update message.\nMake sure that you remove \'new\' from your\n\'Subject:\' line if this was not the desired behavior.\n";
$MESSAGE[$E_STILLREFERENCED]       = "cannot delete object that is still referenced\nby other objects in one of the databases";
$MESSAGE[$E_NOT_ORIGINAL]          = "cannot delete original RIPE181 object through special RPSL update path";
$MESSAGE[$E_NO_MNTNERS_FOUND]      = "no maintainers found for to be updated object\nfirst send a request to (re)create an appropriate maintainer\nfor the orginal object";
$MESSAGE[$E_NO_TL_FOUND]           = "hierarchical authorisation failed,\nno object higher in hierarchy found";
$MESSAGE[$E_NO_TL_CREATION]        = "hierarchical authorisation failed,\ncannot create automatically top level objects\nplease contact <\$HUMAILBOX>";
$MESSAGE[$E_HIER_NO_MNTNERS_FOUND] = "hierarchical authorisation failed,\ncould not find a maintainer for higher level object";

#
# Return codes for syntax checking the objects
#
# we could better have used one unified model for return codes
# but for the mean time we at least keep some aliases to
# avoid even more trouble

$O_OK           =       $OK;
$O_ERROR        =       $NOK;
$O_WARNING      =       22;

$O_INVALIDIP     =24;
$O_INVALIDPREFIX =25;
$O_INVALIDRANGE  =26;
$O_SYNTAXERROR   =27;

$O_NOTFOUND=28;
$O_COULDNOTOPEN=29; 


$MESSAGE[$O_OK]         =       "object OK";
$MESSAGE[$O_ERROR]      =       "object has errors";
$MESSAGE[$O_WARNING]    =       "object has warnings";

#
# possible actions for an entry

$ADDACTION="ADD";
$DELETEACTION="DEL";
$CHANGEACTION="CHANGE";
$SKIPACTION="SKIP";

#
# updatecheck, printstat, maintainer, dbadd & dbdel binary options

$NEWOPTION=1;
$DELETEOPTION=2;
$MODIFYOPTION=4;
$OVERRIDEOPTION=8;
$NOCHECKSOPTION=16;
$OKOPTION=32;
$NOOPOPTION=64;
$FAILEDOPTION=128;
$BACKWARDCOMPATIBILITYOPTION=256;
$ASSIGNEDNICOPTION=512;
$USENORMALMAINTAINERATTR=1024;
$RPSLCONVERSIONOPTION=2048;

#
# donetdbm (binary) options

$CLASSLESSOPTION=1;
$CLEANOPTION=2;
$CONVERT2RPSLOPTION=4;
$KEEPRPSLOPTION=8;

#
# db(cl)open options

$DBOPENWRITEOPTION=1;
$DBOPENCLASSLESSONLYOPTION=2;

#
# dbmatch & lookupandprint (binary) options

$INTERSECTIONOPTION=1;
$ALLLESSSPECIFICOPTION=2;
$MORESPECIFICOPTION=4;
$ALLMORESPECIFICOPTION=8;
$NONRECURSIVEOPTION=16;
$FASTOPTION=32;
$NOSYNTACTICSUGAR=64;
$EXACTMATCHOPTION=128;
$EXACTMATCHIPOPTION=256;
$NONEXTERNALRECURSIVEOPTION=512;
$UNIQUEKEYSEARCHOPTION=1024;
$EXPANDOPTION=2048;
$SINGLEOPTION=4096;
$SILENTOPTION=8192;
$CHANGEDATTROPTION=16384;

#
# The version of the inputformat we default to

$UPDATEVERSION=1;

#
# Supported update versions

@UPDATEVERSIONS=($UPDATEVERSION);

#
# The file extension for the current serial number files 

$CURRENTEXTENSION=".CURRENTSERIAL";

#
# The file extension for the oldest available serial number files 

$OLDESTEXTENSION=".OLDESTSERIAL";

#
# used for fast computations in range2prefix

$ONEDIVLOG2=1/log(2);

#
# very tiny value for rounding of real values in range2prefix

$TINYLOGVALUE=(32-(log(2**32-1)*$ONEDIVLOG2))/100;

#
# text for the synthetic objects

%RSANY=(
"rs", "RS-ANY",
"de", "all routes in:\r");

%ASANY=(
"as", "AS-ANY",
"de", "all autonomous systems in:\r");

#
# some options as defined in the config file and 
# are used inside the code itself

$REALTIMEMIRRORAUTHORIZATION="REALTIMEMIRRORAUTHORIZATION";
$NETWORKUPDATEAUTHORIZATION="NETWORKUPDATEAUTHORIZATION";
$MAINTAINERQRYAUTHORIZATION="MAINTAINERQRYAUTHORIZATION";

@REALTIMEMIRRORAUTHORIZATION=();
@NETWORKUPDATEAUTHORIZATION=();
@MAINTAINERQRYAUTHORIZATION=();

#
# the maximal number of country attributes on a line

$MAXCOUNTRIES=7;

#
# The maximal length of a key measured in characters that is *not* indexed

$SMALLESTKEY=1;

#
# maximal number of initials for NIC handles

$MAXLENGTHINITIALS=4;

#
# which characters are valid for an attribute 
# Note: the * is for the error attribute!

$VALIDATTRCHAR='\w\-\*';

#
# valid domain name regular expression

$DOMAINNAME='[a-zA-Z\d]+((\.|\-+)[a-zA-Z\d]+)*'; 

$MIGHTBEADOMAINNAME='[a-zA-Z\d]+((\.|\-+)[a-zA-Z\d]+)*'; 

#
# valid source attribute regular expression

$SOURCENAME='([A-Z\d]+[A-Z\d\-]*[A-Z][A-Z\d\-]*[A-Z\d]|[A-Z]{2,2})';

#
# the prefix that is used for auto nichandle assignments

$AUTONICPREFIX="AUTO-";
$AUTONICPREFIXREGULAR='AUTO\-';

#
# some common titles - only use lower case

$TITLES='(m[rs]s?|drs?|ir|ing|sign|herr|hr|frau|prof\S*)\.? +';

#
# regular expression for splitting up file names in path & name component

$SPLITFILENAME='^\s*(\S+\/)?([^\/\s]+)\s*$';

#
# ip regular expressions

#
# generic

$VALIDPREFIXKEY='[\d\:\.a-f]+\/\d+';

#
# this one has interesting (but no fatal) problems with perl5 & grep, see whoisd

$QUADPART=      '[12][0-4]\d|25[0-5]|1?[1-9]?\d';
$PADDEDQUADPART='\.0*[12][0-4]\d|\.0*25[0-5]|\.0*1?[1-9]?\d';

$VALIDIP4='0*('.$QUADPART.')('.$PADDEDQUADPART.'){0,3}';

$VALIDFULLIP4='0*('.$QUADPART.')('.$PADDEDQUADPART.'){3,3}';

$VALIDIP4PREFIXLENGTH='0*(3[012]|[12]?[\d])';

$VALIDIP4PREFIX=$VALIDIP4.'\/'.$VALIDIP4PREFIXLENGTH;

$VALIDFULLIP4PREFIX=$VALIDFULLIP4.'\/'.$VALIDIP4PREFIXLENGTH;

$VALIDIP4PREFIXKEY=$VALIDFULLIP4PREFIX;

#
# for ipv6

$VALIDIP6='[\da-f]{1,4}(\:[\da-f]{1,4}){7}';

$VALIDIP6PREFIX='[\d\:a-f]+\:[\d\:a-f]+\/\d+';

$VALIDIP6PREFIXKEY=$VALIDIP6.'\/\d+';


#
# the attribute value to be used for deleted objects

$DELETEDOBJECT="XX";

#
# what is the extension for classless databases ?

$CLASSLESSEXT=".cl";


#
# what is the extension for the overflow files ?

$OVERFLOWEXTENSION=".overflow.";

#
# what is the key for finding a new overflow number

$OVERFLOWKEY="\t";

#
# what is the prefix before the offset when we find an overflow instead
# of offset values

$OVERFLOWPREFIX="\t";
$OVERFLOWPREFIXREGULAR='\t';

#
# NOTEXISTINGPREFIXESKEY 
#
# key to find the list of existing prefixes

$NOTEXISTINGPREFIXESKEY=$OVERFLOWKEY.$OVERFLOWKEY;

#
# which string do we use as 'binding' for uniquekeys

$UNIQUEKEYBINDING="\t";

#
# maximal number of entries/objects that we read & process at a time
#
# entries/objects are stored in a list which length is of the order
# of $MAXLISTLENGTH entries

$MAXLISTLENGTH=50000;

#
# this value determines the maximal length of a string 
# during processing
#
# usually we are talking about prefix keys:
#
# example: 536870912/8
#
# that is components are about 10 bytes long
# and the maximal string length is thus 10*$MAXSTRINGCOMPONENTS
#
# the more components we allow, the longer in memory copies take
# the less components we allow, the more disk accesses we need

$MAXSTRINGCOMPONENTS=300;

#
# line continuation length suffix

$CONTINUATIONSUFFIX=" connectlength";

#
# binding value for offset and size of object
#
# This one should ***always*** be equal to '.'
#
# This allows us to do (easy & fast) sorting of offsets although
# the size of the object is connected as a suffix !!!!
#
# Example: 3.100 (object at offset 3 & size is 100)

$SIZESUFFIXBINDING=".";
$SIZESUFFIXBINDINGREGULAR='\.';                 

#
# ANSI REAL def:

$REAL='(\-|\+)?\s*(\d+)(\.\d+)?([eE][\-\+]\d+)?';

#
# allowed routing protocols plus aliases for IPv6

%IPV6PROTOCOLS=(
"idrpv6", "IDRPv6", 
"bgp4+", "BGP4+", 
"ripv6", "RIPng", 
"ripng", "RIPng",
"static", "STATIC"
);

1;


#
#       End of included 'defines.pl' data is here
#

#
#       The file 'doripe2rpsl.pl' is included here
#



#
# $Id: ripe2rpsl,v 1.1 2001/09/13 11:04:09 andrei Exp $

# Copyright (c) 1997,1998 by the University of Southern California
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by the University of Southern California, Information
# Sciences Institute. The name of the USC may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
# OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
# OR PERFORMANCE OF THIS SOFTWARE.

#
# Copyright (c) 1998, 1999 by Qwest Communications International
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by Qwest Communications International. The name of Qwest
# Communications International may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# Qwest Communications International DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL Qwest Communications International OR ANY OTHER 
# CONTRIBUTOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
# DAMAGES, WHETHER IN CONTRACT, TORT, OR OTHER FORM OF ACTION, ARISING 
# OUT OF OR IN CONNECTION WITH, THE USE OR PERFORMANCE OF THIS SOFTWARE.

#
#  Author(s): Cengiz Alaettinoglu <cengiz@isi.edu>
#  Author(s): David Kessens <david@Qwest.net>

sub fix_policy_attr_errors {
    local(*str)=@_;
    
    $str=~ s/[^\S\r\n]+/ /g;
    $str=~ s/ *([\r\n]+) */$1/g;
    
    $str=~ s/\bOR\s+OR\b/OR/ig;
    $str=~ s/\bAND\s+AND\b/AND/ig;
    $str=~ s/\bAND\s+ANY\b/ANY AND/g;
    while ($str=~ s/\((AND|OR)\s*([^\s\)][^\)]+\))/$1 \($2/gi) {};
  
    $str=~ s/\=20//gi;
  
    $str=~ s/([^\d\.]\d+\.\d+\.\d+)(\/\d+[^\d])/$1\.0$2/g;
    $str=~ s/([^\d\.]\d+\.\d+)(\/\d+[^\d])/$1\.0\.0$2/g;
}

sub fix_filter_errors {
    local(*str)=@_;

    $str =~ s/^\d+\s+//g;
    $str =~ s/(AS\d+\s*),/$1/gi; # potentially dangerous when input is rpsl
    $str =~ s/\"//g;
    $str=~ s/(<[^>]+\*)1040\b/$1*>/g;
#    $str=~ s/(\s*)$/\>$1/ if (scalar($str=~ tr/\</\</)-scalar($str=~ tr/\>/\>/)==1);
#    $str=~ s/(\s*)$/\}$1/ if (scalar($str=~ tr/\{/\{/)-scalar($str=~ tr/\}/\}/)==1);

    local(@lines)=();

    foreach (split(/([^a-zA-Z\d\-\_]+)/, $str)) {
       if (/^[^a-zA-Z\d\-\_]+$/) {
         push(@lines, $_);
         next;
       }
       if (/^(AS\d+)(AS\d+)+$/i) {
         foreach (split(/(AS\d+)/i)) {
           push(@lines, "$_ ");
         }
         next;
       }
       $_="RS-".$_ if ((/^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?$/) && # a word
                       (! /^(AS\d+|AS-.*|RS-.*|AND|NOT|OR|ANY)$/i));
       push(@lines, $_);
    }

    $str=join("", @lines);

}

sub fix_email_errors {
    local(*str, $options)=@_;

    my(@lines)=();

    if (!$options) {

       foreach (split(/\n/,  $str)) {

          if (! /\@/) {

             #
             # fix some well known people ...
          
             if (/^Peter\s+Lothberg$/i) {
                push(@lines, "roll\@stupi.se");
                next;
             }
             elsif (/^Ulla\s+Sandberg$/i) {
                push(@lines, "ulla\@stupi.se");
                next;
             }

          }

          push(@lines, $_);

       }

       $str=join("\n", @lines);
       @lines=();

    }

    foreach (split(/(\s+)/,  $str)) {
    
       if (/^\s+$/) {
          if (/\n/) {
             push(@lines, "\n");
          }
          elsif (/\r/) {
             push(@lines, "\r");
          }
          else {
             push(@lines, " ");
          }
          next;
       }

       #
       # get rid of <> around mail addresses

       s/^\<//g && s/\>$//g;

       #
       # get rid of trailing dots 

       s/\.$//; 

       #
       # try to repair tld's if possible

       (/\@[\w\-]+$/) &&
       ((s/(com|org|net|edu|gov)$/.$1/i) ||
        (s/(com?|org|net|edu|gov)(..)$/.$1.$2/i) ||
        ((!$options) && ($_.=".unknown")));

       push(@lines, $_);

    }

    $str=join("", @lines);

}

sub fix_date_errors() {
    local(*str)=@_;

    my(@lines)=();

    foreach (split(/(\s+)/,  $str)) {
       if (/^\s+$/) {
          if (/\n/) {
             push(@lines, "\n");
          }
          elsif (/\r/) {
             push(@lines, "\r");
          }
          else {
             push(@lines, " ");
          }
          next;
       }
       /^\d\d\.\d\d\.\d\d$/ && s/\.//g;
       s/^(\d{6})$/19$1/g;
       push(@lines, $_);
    }

    $str=join("", @lines);

}

sub fix_mntner_errors() {
    local(*str)=@_;

    my(@lines)=();

    foreach (split(/(\s+)/,  $str)) {
       if (/^\s+$/) {
          if (/\n/) {
             push(@lines, "\n");
          }
          elsif (/\r/) {
             push(@lines, "\r");
          }
          else {
             push(@lines, " ");
          }
          next;
       }
# AR 20000504 
#       s/^AS\d+$/MNT-$&/i ||
#       s/^AS-/MNT-AS-/i ||
#       s/^RS-/MNT-RS-/i ||
#       s/^\d/MNT-$&/gi;
       
       # warn about invalid maintainer names
       if ($WARN_INVALID_MNTNER) {
           if (m/^AS\d+$/i || m/^(AS|RS)-/i || m/^\d/i) {
               $_ .= "  # ERROR: invalid RPSL maintainer name";
           }
       }
       push(@lines, $_);
    }

    $str=join("", @lines);

}

sub uniqify_listify() {
    local(*str) = @_;
    
    my(%items)=();
    my(@lines)=();
    my($i)=0;

    foreach (grep( $_ && ((++$items{$_})==1), split(/[\s,]/, $str))) {
       if ($i % 5) {
          push(@lines, ", ", $_);
       }
       else {
          if (@lines) {
             push(@lines, ",\r", $_);
          }
          else {
             push(@lines, $_);
          }
          $i=0;
       }
       $i++;
    }
    $str=join("", @lines);

}


#
# ripe2rpsl
#
# converts RIPE181 %entry to RPSL %entry
# 
# returns new type of the object
#
# $options=1 assume that the object was sent in as RPSL
#            and convert only the RIPE181 attributes/object type

sub ripe2rpsl {
    local(*entry, $type, $options)=@_; 

    local($str, $rest);
    my($line, @lines, $lastline, $thisline, 
       $peeras, $pref, $br, $peerbr);

    #
    # delete as-exclude/advisory attributes

    delete($entry{"ae"});
    delete($entry{"av"});

    #
    # the following are all kind of private Merit attributes: 
    delete($entry{"ne"});
    delete($entry{"np"});
    delete($entry{"cp"});
    delete($entry{"ri"});
    delete($entry{"rs"}) 
        if ((defined($entry{"an"})) || (defined($entry{"ir"})));
    delete($entry{"rx"}) 
        if ((defined($entry{"an"})) || (defined($entry{"ir"})));

    if ($options) {

       #
       # remove line continuation information
# unnecessary "fix" shane 2001-01-30
#       foreach ("al", "cl", "ho") {
#          delete($entry{$_}) if (/$CONTINUATIONSUFFIX$/o);
#       }

# unnecessary "fix" shane 2001-01-30
#       $entry{"al"} =~ tr/\n/ /  if $entry{"al"};
#       $entry{"cl"} =~ tr/\n/ /  if $entry{"cl"};
#       $entry{"ho"} =~ tr/\n/ /  if $entry{"ho"};

    }
    else {

       #
       # remove garbage values
       
       foreach ("em", "fx", "ny", "ph") {
          $entry{$_}=~ s/(^|\n)(\<?(NONE(\s+yet)?|no\s+fax|no\s+\-?e\-?mail)\>?|nobody\@nowhere\.net)\s*($|\n)/\n/i;
          $entry{$_}=~ s/\n+$/\n/g;
          $entry{$_}=~ s/^\n//;
          $entry{$_}=~ s/\n$//;
          delete($entry{$_}) if (/^\s*$/);
       }

       #
       # remove line continuation information
       foreach (keys %entry) {
          delete($entry{$_}) if (/$CONTINUATIONSUFFIX$/o);
       }


       # 
       # if the following attributes are missing insert them
       if ($FIX_MISSING) {
           # insert required maintainers - different for aut-nums
           if ($entry{"mb"} =~ /^\s*$/) {
               if (($type eq "an") && $PROTECT_AUT_NUM) {
                   $entry{"mb"} = "RIPE-NCC-AN-MNT  # WARNING: maintainer added to protect object";
	       } elsif ($type !~ /^dn|pn|ro$/) {
                   $entry{"mb"} = "RIPE-NCC-NONE-MNT";
               }
           } 

           $entry{"ph"}="+0 # unknown phone number"  if (($type eq "pn") && ($entry{"ph"}=~ /^\s*$/));
           $entry{"ad"}="unknown address"  if (($type=~ /^pn|ro$/) && ($entry{"ad"}=~ /^\s*$/));
           $entry{"de"}="no description" if (($type=~ /^in|an|cm|am$/) && ($entry{"de"}=~ /^\s*$/));
           $entry{"na"}="no name" if (($type eq "in") && ($entry{"na"}=~ /^\s*$/));
           $entry{"tc"}=$entry{"ac"} if (($type eq "in") && ($entry{"tc"}=~ /^\s*$/) && ($entry{"ac"}=~ /\S/));
           $entry{"ac"}=$entry{"tc"} if (($type eq "in") && ($entry{"ac"}=~ /^\s*$/) && ($entry{"tc"}=~ /\S/));
           $entry{"tc"}=$entry{"ac"} if (($type eq "dn") && ($entry{"tc"}=~ /^\s*$/) && ($entry{"ac"}=~ /\S/));
           $entry{"ac"}=$entry{"tc"} if (($type eq "dn") && ($entry{"ac"}=~ /^\s*$/) && ($entry{"tc"}=~ /\S/));
           $entry{"zc"}=$entry{"tc"} if (($type eq "dn") && ($entry{"zc"}=~ /^\s*$/) && ($entry{"tc"}=~ /\S/));

           # 
           # add missing "referral-by" to mntner objects
           if ($type eq "mt") {
               $entry{"rb"} ||= "RIPE-DBM-MNT";
           }

           # add as-name, if missing
           if ($type eq "an") {
               $entry{"aa"} ||= "UNSPECIFIED";
           }
           if ($CONVERT_AS_NAME) {
               $entry{"aa"} =~ 
                  s/^(AS)-(.*)$/ASN-$2  # $MATCH converted to ASN-$2 for RPSL compliance/i;
           }
       }


       #  
       # the following attributes are now single valued
       # mnt-by is a multi-valued list in RFC2622, shane 2001-01-08
       #$entry{"mb"} =~ tr/\n/ /  if defined($entry{"mb"});
       # mnt-lower isn't strictly defined in RFC2725, shane 2001-01-30
       #$entry{"ml"} =~ tr/\n/ /  if defined($entry{"ml"});
       # as-list/members is a multi-valued list in RFC2622, shane 2001-01-30
       #$entry{"al"} =~ tr/\n/ /  if defined($entry{"al"});
       # member-of is a multi-valued list in RFC2622, shane 2001-01-30
       #$entry{"cl"} =~ tr/\n/ /  if defined($entry{"cl"});
       # holes is a multi-valued special in RFC2622, shane 2001-01-30
       #$entry{"ho"} =~ tr/\n/ /  if defined($entry{"ho"});

       #
       # convert to white space line continuations and remove white space

       if ($USE_MULTILINE) {
           $entry{"de"} =~ tr/\n/\r/ if defined($entry{"de"});
           $entry{"tb"} =~ tr/\n/\r/ if defined($entry{"tb"});
           $entry{"tx"} =~ tr/\n/\r/ if defined($entry{"tx"});
           $entry{"ad"} =~ tr/\n/\r/ if defined($entry{"ad"});
           $entry{"rm"} =~ tr/\n/\r/ if defined($entry{"rm"});
           $entry{"de"} =~ s/\r *(\r|$)/$1/g if defined($entry{"de"});
           $entry{"tb"} =~ s/\r *(\r|$)/$1/g if defined($entry{"tb"});
           $entry{"tx"} =~ s/\r *(\r|$)/$1/g if defined($entry{"tx"});
           $entry{"ad"} =~ s/\r *(\r|$)/$1/g if defined($entry{"ad"});
           $entry{"rm"} =~ s/\r *(\r|$)/$1/g if defined($entry{"rm"});
       }

       
       #
       # MCI contained comments at many wrong places ...
       # also, this makes sure to get rid of '# EOF' at end of files.

       $entry{"so"}=$1 if ($entry{"so"}=~ /^(\w+)/);
    
       #
       # fix st
       if (defined($entry{"st"})) {
          $entry{"st"}=~ s/^(\s*)D(ELEGATED)?(\s*)$/$1ALLOCATED UNSPECIFIED$3/i;
       }

       #
       # fix ch
       if (defined($entry{"ch"})) {

          $str=$entry{"ch"};

          $str=~ s/,(\s*\d)/$1/g;
          &fix_email_errors(*str, $options);
          &fix_date_errors(*str);

          @lines = ();
          foreach (split(/\n/, $str)) {
          
             @fields = split(/\s+/, $_);
             if ($fields[$#fields] =~ /^\d{8}$/) {
                push(@lines, $fields[0]." ".$fields[$#fields]);
                next;
             }

             push(@lines, $fields[0]." ".$DATE);
          }
# cengiz          $entry{"ch"}=join("\n", @lines, $CHANGEDLINE);

       }
       else {
# cengiz          $entry{"ch"}=$CHANGEDLINE;
       }
       
       #
       # fix wd
       if (defined($entry{"wd"})) {

          $str=$entry{"wd"};

          &fix_date_errors(*str);
       
          @lines = ();

          foreach (split(/\n/, $str)) {
          
             if (/^\s*\S*\s*(\d{8,8})\s*$/) {
                push(@lines, $1);
                next;
             }
  
             push(@lines, $DATE);

          }
          $entry{"wd"}=$lines[$#lines];

       }

       if (defined($entry{"mt"})) {
          $str=$entry{"mt"};
          &fix_mntner_errors(*str);
          $entry{"mt"}=$str;
       }

       if (defined($entry{"mb"})) {
          $str=$entry{"mb"};
          &fix_mntner_errors(*str);
          $entry{"mb"}=$str;
       }
    
       if (defined($entry{"ml"})) {
          $str=$entry{"ml"}; 
          &fix_mntner_errors(*str);
          $entry{"ml"}=$str; 
       }
    
       if (defined($entry{"em"})) {
          $str=$entry{"em"}; 
          &fix_email_errors(*str, $options);
          $entry{"em"}=$str; 
       }
    
       if (defined($entry{"dt"})) {
          $str=$entry{"dt"};  
          &fix_email_errors(*str, $options);
          $entry{"dt"}=$str; 
       }

       #
       # fix inet-rtr

       if (defined($entry{"ir"})) {
       
          $line=&convert2domainname($entry{"ir"});

          if ($line ne $entry{"ir"}) {

             #
             # add information to be able to generate a uniquekey
             # based on the old value of the entry, DNS cannot be trusted
             # to always give the same value back and thus 
             # 'syncdb' would (often) have a lot of trouble recognizing
             # the objects as the same and people would come
             # to me and ask how to explain those strange problems ...
             # this code can go when entering RPSL transition phase III
             #
             # see also special code in 'enukey()'
             #
             # David K.

             if ((%RPSLCONVERSION) && ($entry{"ir"}=~ /^\d+\.\d+\.\d+\.\d+$/)) {
                if (defined($entry{"rm"})) {
                   $entry{"rm"}=join("\n", $entry{"rm"}, "converted from \'inet\-rtr\: ".$entry{"ir"}."\'");
                }
                else {
                   $entry{"rm"}="converted from \'inet\-rtr\: ".$entry{"ir"}."\'";
                }
             }

             if ($line) {
                $entry{"ir"}=$line;
             }
             else {
                $entry{"ir"}=~ s/^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)\s*$/$4.$3.$2.$1.in-addr.arpa/;
             }

          }

       }

       if (defined($entry{"ho"})) {
          $str=$entry{"ho"}; 
          &uniqify_listify(*str);
          $entry{"ho"}=$str; 
       }
    }

    #
    # fix guardian & notify (note: order is important!)
    if (defined($entry{"gd"})) {
       if ($entry{"ny"}) {
          $entry{"ny"}=$entry{"gd"}."\n".$entry{"ny"}; 
       }
       else {
          $entry{"ny"}=$entry{"gd"}; 
       }
    }

    if (defined($entry{"ny"})) {
       $str=$entry{"ny"};
       &fix_email_errors(*str, $options);
       my(%items)=();
       $entry{"ny"}=join("\n", grep( $_ && ((++$items{$_})==1), split(/\s*\n+\s*/, $str)));
    }
  
    
    #
    # fix community
    if (defined($entry{"cm"})) {
       $entry{"rs"}="RS-".delete($entry{"cm"});
       $entry{"mr"}="any";
       $type="rs";
    }

    #
    # fix comm-list
    if (defined($entry{"cl"})) {
       $entry{"mo"}="RS-".join(", RS-", split(/[\s,]+/, delete($entry{"cl"})));
    }

    #
    # fix community
    if (defined($entry{"am"})) {
       $entry{"as"}=delete($entry{"am"});
       $type="as";
    }

    #
    # fix as-list
    if (defined($entry{"al"})) {
       $str=delete($entry{"al"});
       $str =~ s/([A-Z0-9\-_])([ \t]+AS)/$1,$2/ig;
# unnecessary "fix" shane 2001-01-30
#       &uniqify_listify(*str);
       $entry{"ms"}=$str;
    }

    
    #
    # interas-in lines
    
    if (defined($entry{"it"})) {

       $str=delete($entry{"it"});
       &fix_policy_attr_errors(*str);
  
       $lastline="";
       $thisline="";
       @lines=();

       foreach (split(/\n/, $entry{"it"})) {
          ($peeras, $br, $peerbr, $rest) = split(/ +/, $_, 4);
          $rest=~ /\(\s*PREF\s*=\s*([^)\s]*)\s*\)\s*(.*)$/i;
          $pref=$1;
          $rest=$2;
          &fix_filter_errors(*rest);

          $thisline = "$peeras%$br%$peerbr%$pref";
          if ($thisline eq $lastline) {
             $lines[$#lines] .= " " . $rest if (@lines);
          }
          else {
             push(@lines, join("", "from ", $peeras, $peerbr, " at ", $br, 
                                   "\raction pref=", $pref,
                                   ";\raccept ", $rest));
          }
          $lastline = $thisline;
       }

       if ($entry{"ip"}) {
          $entry{"ip"}.="\n".join("\n", @lines);
       }
       else {
          $entry{"ip"}=join("\n", @lines);
       }

    }

    #
    # interas-out lines
    
    if (defined($entry{"io"})) {

       $str=delete($entry{"io"});
       &fix_policy_attr_errors(*str);
  
       $lastline="";
       $thisline="";
       @lines=();

       foreach (split(/\n/, $entry{"io"})) {
          
          ($peeras, $br, $peerbr, $rest) = split(/ +/, $_, 4);
          if ($rest =~ /\(\s*METRIC\-OUT\s*=\s*([^)\s]*)\s*\)?\s*(.*)$/i) {
             $pref = $1;
             $rest = $2;
          }
          else {
             $pref = "?";
          }
          &fix_filter_errors(*rest);

          $thisline = "$peeras%$br%$peerbr%$pref";
          if ($thisline eq $lastline) {
             $lines[$#lines] .= " " . $rest if (@lines);
          }
          else {
           
             if ($pref eq "?") {
                push(@lines, join("", "to ", $peeras, $peerbr, " at ", $br, 
                                      "\rannounce ", $rest));
             }
             else {
                push(@lines, join("", "to ", $peeras, $peerbr, " at ", $br, 
                                      "\raction med=", $pref,
                                      ";\rannounce ", $rest));
             }

          }
       
          $lastline = $thisline;
       }

       if ($entry{"ep"}) {
          $entry{"ep"}.="\n".join("\n", @lines);
       }
       else {
          $entry{"ep"}=join("\n", @lines);
       }

       

    }

    #
    # as-in lines
    if (defined($entry{"ai"})) {

       $str=delete($entry{"ai"});

       &fix_policy_attr_errors(*str);
       $str=~ s/\bfrom\s+//gi && $str=~ s/\s+accept\s+/ /gi;
       
       $lastline="";
       $thisline="";
       @lines=();
    
       foreach (split(/\n/, $str)) {
          
          ($peeras, $pref, $rest) = split(/ +/, $_, 3);
          if (! $rest) {
            $rest = $pref;
            $pref = "";
          }
          &fix_filter_errors(*rest);

          $thisline = "$peeras%$pref";
          if ($thisline eq $lastline) {
             $lines[$#lines] .= " " . $rest if (@lines);
          }
          else {
            if ($pref) {
              push(@lines, join("", "from ", $peeras, "\raction pref=", $pref, 
                                ";\raccept ", $rest));
            } else {
              push(@lines, join("", "from ", $peeras, "\raccept ", $rest));           
            }
          }
          $lastline = $thisline;
       }

       foreach (@lines) {
         s/\b(accept) (AND NOT)/$1 ANY $2/i;
         s/\b(NOT)$/$1 {}/i;
         s/\b(OR)$/$1 {}/i;
         s/\b(AND)$/$1 {}/i;
       }

       if ($entry{"ip"}) {
          $entry{"ip"}.="\n".join("\n", @lines);
       }
       else {
          $entry{"ip"}=join("\n", @lines);
       }

    }

    #
    # as-out lines
    if (defined($entry{"ao"})) {

       $str=delete($entry{"ao"});

       &fix_policy_attr_errors(*str);
       $str=~ s/\bto\s+//gi && $str=~ s/\s+announce\s+/ /gi;

       $lastline="";
       $thisline="";
       @lines=();

       foreach (split(/\n/, $str)) {
          
          ($peeras, $rest)=split(/ +/, $_, 2);
          &fix_filter_errors(*rest);

          $thisline = "$peeras";
          if ($thisline eq $lastline) {
             $lines[$#lines] .= " " . $rest if (@lines);
          }
          else {
             push(@lines, join("", "to ", $peeras, "\rannounce ", $rest));
          }
          $lastline = $thisline;

       }

       foreach (@lines) {
         s/\b(announce) (AND NOT)\b/$1 ANY $2/i;
         s/\b(NOT)$/$1 {}/i;
         s/\b(OR)$/$1 {}/i;
         s/\b(AND)$/$1 {}/i;
       }

       if ($entry{"ep"}) {
          $entry{"ep"}.="\n".join("\n", @lines);
       }
       else {
          $entry{"ep"}=join("\n", @lines);
       }

    }

    #
    # fix default
    
    if ((defined($entry{"df"})) && ($entry{"df"}!~ /to/i)) {
      $str=$entry{"df"};
      &fix_policy_attr_errors(*str);
      $str=~s/\bdefault\b/ANY/g;
      $str=~s/\bstatic\b/ANY/g;

      @lines=();
      foreach (split(/\n/, $str)) {
        ($peeras, $pref, $rest) = split(/ +/, $_, 3);
        $rest = "ANY" if (!$rest);
        push(@lines, join("", "to ", $peeras, 
                          "\raction pref=", $pref, 
                          ";\rnetworks ", $rest)); 
      }
      $entry{"df"}=join("\n", @lines);
    }

    #
    # fix peer
    if ((defined($entry{"pe"})) && ($entry{"pe"}=~ /^\s*\d+\.\d+\./)) {
       my(@tmp);
       @lines=();
       foreach (split(/\n/, $entry{"pe"})) {
          s/\bEGP$/BGP4/go;
          s/\bBGP$/BGP4/go;
          s/\bRIP2$/RIP/go;
          @tmp=split(/\s+/, $_);
          push(@lines, join(" ", $tmp[2], $tmp[0], "asno($tmp[1])"));
       }
       $entry{"pe"} = join("\n", @lines);
    }

    #
    # fix ifaddr
    if ((defined($entry{"if"})) && ($entry{"if"}!~ /mask|len/i)) {
      @lines = split(/\n/, $entry{"if"});
      for ($i =0; $i <= $#lines; $i++) {
        $mask = 0;
        @fields = split(/\s+/, $lines[$i]);
        foreach (split(/\./, $fields[$#fields])) {
          last if ($_ == 0);
          if ($_ < 128) {
            next;
          }
          if ($_ < 192) {
            $mask+=1;
            next;
          }
          if ($_ < 224) {
            $mask+= 2;
            next;
          }
          if ($_ < 240) {
            $mask+= 3;
            next;
          }
          if ($_ < 248) {
            $mask+= 4;
            next;
          }
          if ($_ < 252) {
            $mask+= 5;
            next;
          }
          if ($_ < 254) {
            $mask+= 6;
            next;
          }
          if ($_ < 255) {
            $mask+= 7;
            next;
          }
          $mask+= 8;
        }
        pop @fields;
        $lines[$i] = join(" ", @fields, "masklen", $mask);
      }
      $entry{"if"} = join("\n", @lines);
    
    }
    
    return $type;
    
}

1;


#
#       End of included 'doripe2rpsl.pl' data is here
#

#
#       The file 'enread.pl' is included here
#


#
#       enread - read RIPE database entry
#
#       $RCSfile: ripe2rpsl,v $
#       $Revision: 1.1 $
#       $Author: andrei $
#       $Date: 2001/09/13 11:04:09 $

# Original code is written by various authors

# Copyright (c) 1993, 1994, 1995, 1996, 1997  The TERENA Association
# Copyright (c) 1998                              RIPE NCC
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the author not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Copyright (c) 1997,1998 by the University of Southern California
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by the University of Southern California, Information
# Sciences Institute. The name of the USC may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
# OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
# OR PERFORMANCE OF THIS SOFTWARE.

#
# Copyright (c) 1998, 1999 by Qwest Communications International
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by Qwest Communications International. The name of Qwest
# Communications International may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# Qwest Communications International DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL Qwest Communications International OR ANY OTHER 
# CONTRIBUTOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
# DAMAGES, WHETHER IN CONTRACT, TORT, OR OTHER FORM OF ACTION, ARISING 
# OUT OF OR IN CONNECTION WITH, THE USE OR PERFORMANCE OF THIS SOFTWARE.

#
# Author(s): David Kessens <david@Qwest.net>

#
#       This routine reads RIPE database entries in %entry and returns the
#       type, "" when nothing has been found, $DELETEDOBJECT when
#       the object has been deleted, and an other invalid type when an 
#       invalid object has been found.
#       When no valid/deleted object has been found %entry is set to ().
#
#       file       file to read from

#
# enread
#
# Take care with changing anything in this routine.
# It is highly optimized for speed, especially for (sorted) big objects.
#
# $offset=#
#         >=0   read from position # and return position first found object
#         =-1   read from current position and return position first found object
#         =-2   read from current position and don't return current position

sub enread {
    local($file, *entry, $offset, $size) = @_;

    my($line,$newtag,$shorttag,$connect,$prefixlength,
       $standardprefixlength,$linelength,@lines);

    my($readsize)=0;
    my($tag)="";
    my($type)="";
    my(@inputlines)=();
    my(@connectlength)=();
    %entry=();

    #
    # select the right file for reading for RPSLCONVERSION
    # special update path data

    $file.=".rpsl" if ($offset=~ /^0[^0]/);
  
    # print STDERR "enread file: $file offset: $offset size: $size\n";
    
    # print STDERR "first line: ", scalar(<$file>); seek($file, $offset, 0);

    if (defined($size)) {
       
       local($object);

       if ($SYSREAD) {
          if (-2!=$offset) {
             if ($offset>=0) {
                $offset=sysseek($file, $offset, 0);
             }
             else {
                $offset=sysseek($file, 0, 1) 
             }
          }
          elsif ($offset>=0) {
             sysseek($file, $offset, 0) 
          }
          &safesysread($file, *object, $size);
       }
       else {
          $offset=tell($file) if ($offset==-1);
          seek($file, $offset, 0) if ($offset>=0);
          &readparagraph($file, *object);
       }

       $object=~ s/\n+$//;

       # print STDERR "enread file: $file offset: $offset size: $size loc: ", tell($file), " ",$object, "-\n";

       ($line,@inputlines)=split(/\n/, $object);

       $line=~ s/\s/ /g;
       
       # print STDERR "$line --- \n", join("\n",@inputlines);

    }
    else {

       # print "no seek $offset $!\n";

       seek($file, $offset, 0) if ($offset>=0);

       # print "seek $!\n";

       #
       # skip empty lines until we find the first data and
       # make sure that we keep the offset
    
       $offset=tell($file) if (-1==$offset);
       while ((defined($line=<$file>)) &&
              (($line=~ /^\s+$/) || ($line=~ /^\s*\#/)
              || ($line=~ /^\s*\%/) || ($line=~ /^(ADD|DEL|UPDATE)/)) ) {
          $offset=tell($file) if (-2!=$offset);
          print STDOUT $line;
       }
       $line=~ s/\s/ /g;

    }
    
    # print "start $!\n";

    # print STDERR "first line: ", $line;
    
    # normal line handling
    if ($line) {
       
       #
       # return immediately if we found a deleted object
       # and we are not in scanning mode during the index
       # process when we intend to skip deleted objects
    
       if ($line=~ /^ *\*?$DELETEDOBJECT *\:/o) {

          return ($DELETEDOBJECT, $offset, 0) if ($offset>=0);

          # print STDERR "XX object $line";
       
          while ($line=~ /^\s*\*?$DELETEDOBJECT\s*\:/o) {
                while ((defined($line=<$file>)) && 
                       ($line ne "\n")) {};
                while ((defined($line=<$file>)) &&
                       (($line=~ /^\s*$/) || ($line=~ /^\s*\#/))) {
                   $offset=tell($file) if (-2!=$offset);
                }; 
          }
          $line=~ s/\s/ /g;

       }
       
       for (;;) {
          
          $linelength=length($line);

          # special case password handling (gack gack gack)
          if ($line =~ /^ *password:/) {
              print $line, "\n";
          }

          elsif (($line=~ s/^(\*)?([^\*\: ]+)( *\: *)//) ||
              ((@lines) && (($line=~ s/^(  +)//) || ($line=~ s/^()\#/\#/)))) {
             
             $readsize+=$linelength;

             if ($3) {
                
                #
                # we found another attribute

                $standardprefixlength=length($1)+length($2)+length($3);

                ($newtag=$2)=~ tr/A-Z/a-z/;
                $connect="\n";

             }
             else {

                #
                # we have a line continuation

                $prefixlength=length($1)-$standardprefixlength;

                push(@connectlength, ($prefixlength<=0)?2:($prefixlength+2));                

                $connect="\r";
                
             }
             
             #
             # remove trailing spaces
             
             $line=~ s/ *$//;
             
             if ($tag eq $newtag) {
             
                # print STDERR "tag: ", $tag, "\n";
             
                # tag is same as previous one
             
                if ($line) {
                   # print STDERR "tag: $tag value: $line\n";
                   push(@lines, $connect, $line);
                }
                else {
                   push(@lines, $connect, "")  if ($lines[$#lines]);
                   #&logmessage("ERRLOG", "enread: empty attribute, normal $tag (offset: ".$offset." ".$offset." ".tell($file).") in line: $newtag:");
                }
             
             }
             else {
                
                #
                # tag could have been changed
                
                #
                # store old tag
                
                if ($entry{$shorttag}) {
                   $entry{$shorttag}=join("", $entry{$shorttag}, $connect, @lines) if (@lines);
                }
                else {
                   $entry{$shorttag}=join("", @lines) if (@lines);
                }

                #
                # store line continuation lengths

                if (@connectlength) {
                   if ($entry{$shorttag.$CONTINUATIONSUFFIX}) {
                      $entry{$shorttag.$CONTINUATIONSUFFIX}=join(" ", $entry{$shorttag.$CONTINUATIONSUFFIX}, @connectlength);
                   }
                   else {
                      $entry{$shorttag.$CONTINUATIONSUFFIX}=join(" ", @connectlength);
                   }
                }
                
                $tag=$newtag;
                
                $shorttag=$ATTR{$tag};
                
                if (!$shorttag) {
                   &logmessage("ERRLOG", "enread: unknown attribute: \'$tag\' found, (offset: ".$offset." ".$offset." ".tell($file).") in line: $tag: ".$line);
                   $shorttag=$tag;
                }
                
                #
                # we keep the type of the object
                
                # print STDERR "newtag: ", keys %OBJATSQ, $tag, "\n";
                
                $type=$shorttag if ((!$type) && ($OBJATSQ{$shorttag}));
                
                #
                # print STDERR "type: ", $type, "\n";
                
                if ($line) {
                   # print STDERR "newtag: $tag type: $type value: $value\n";
                   @lines=($line);

                }
                else {
                   @lines=("");
                   #&logmessage("ERRLOG", "enread: empty attribute, newtag $newtag (offset: ".$offset." ".$offset." ".tell($file).") in line:".$line);
                }
             
             }
             
          }
          else {
             
             # now we have the following possibilties:
             #
             # - we are at the end of the object
             # - we found a comment
             # - we have an error condition
             #
             # let's assume the first possibility first since
             # it is most common
             
             if ($line=~ /^ *$/) {

                #   
                # end of object
                
                #
                # store old tag
                
                if ($entry{$shorttag}) {
                   $entry{$shorttag}=join("", $entry{$shorttag},$connect,@lines);
                }
                else {
                   $entry{$shorttag}=join("", @lines);
                }
                
                #
                # store line continuation lengths

                if ($entry{$shorttag.$CONTINUATIONSUFFIX}) {
                   $entry{$shorttag.$CONTINUATIONSUFFIX}=join(" ", $entry{$shorttag.$CONTINUATIONSUFFIX}, @connectlength) if (@connectlength);
                }
                else {
                   $entry{$shorttag.$CONTINUATIONSUFFIX}=join(" ", @connectlength) if (@connectlength);
                }
      
                # print STDERR "type: $type ",$entry{"so"}." $shorttag entry:\n", %entry, "\n";
                
                return ($type, $offset, $readsize) if ($type);
                
                &logmessage("ERRLOG", "enread: object has no type (offset: ".$offset." ".$offset." ".tell($file).") in line: ".$line);  
                   
                %entry=();
                   
                # just create a type that is not the same as others and 
                # that is for sure invalid ...
                      
                return ($DELETEDOBJECT.$DELETEDOBJECT, $offset, 0);
                      
             }
             elsif ($line!~ /^\#/) {
  
                #              
                # no comment, no end of object
                #
                # we have an error condition
                #
                
                # print STDERR "$offset $line";
                      
                &logmessage("ERRLOG", "enread: no attribute in line (tag: $tag, type: $type) (offset: ".$offset." ".$offset." ".tell($file).") in line: ".$line);  
                
                # skip rest of object
                
                if (!defined($size)) {         
                   while ((defined($line=<$file>)) && ($line!~ /^\s+$/)) {}
                }
     
                %entry=();
                      
                # just create a type that is not the same as others and 
                # that is for sure invalid ...
                      
                return ($DELETEDOBJECT.$DELETEDOBJECT, $offset, 0);
                
             }
             
          }
       
          if (defined($size)) {
             ($line=shift(@inputlines)." ")=~ s/\s/ /g;
             #print STDERR "next: -", $line,"-", @inputlines;
          }
          else {
             ($line=<$file>)=~ s/\s/ /g;
             #print STDERR "line: ",$line,"\n";
          }
          
       
       }
  
    }
    else {
       return();
    }

}

1;


#
#       End of included 'enread.pl' data is here
#

#
#       The file 'enwrite.pl' is included here
#



#
#       enwrite - write RIPE database entry
#
#       $RCSfile: ripe2rpsl,v $
#       $Revision: 1.1 $
#       $Author: andrei $
#       $Date: 2001/09/13 11:04:09 $
#
#       This routine writes a RIPE database entry to standard output
#       in long or short form.
#
#       Arguments:
#       $output         file handle for output
#       *object         pointer to assoc array with database entry
#       $witherrors     boolean flag for with or without error messages

#  Original code is written by various authors

# Copyright (c) 1993, 1994, 1995, 1996, 1997  The TERENA Association
# Copyright (c) 1998                              RIPE NCC
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the author not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Copyright (c) 1997,1998 by the University of Southern California
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by the University of Southern California, Information
# Sciences Institute. The name of the USC may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
# OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
# OR PERFORMANCE OF THIS SOFTWARE.

#
# Copyright (c) 1998, 1999 by Qwest Communications International
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for lawful non-commercial
# purposes and without fee is hereby granted, provided that the above
# copyright notice appear in all copies and that both the copyright
# notice and this permission notice appear in supporting documentation,
# and that any documentation, advertising materials, and other materials
# related to such distribution and use acknowledge that the software was
# developed by Qwest Communications International. The name of Qwest
# Communications International may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# Qwest Communications International DOES NOT MAKE ANY
# REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
# PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
# TITLE, AND NON-INFRINGEMENT.
#
# IN NO EVENT SHALL Qwest Communications International OR ANY OTHER 
# CONTRIBUTOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
# DAMAGES, WHETHER IN CONTRACT, TORT, OR OTHER FORM OF ACTION, ARISING 
# OUT OF OR IN CONNECTION WITH, THE USE OR PERFORMANCE OF THIS SOFTWARE.

#
#  Author(s): David Kessens <david@Qwest.net>

sub enwrite {
    local($output, *object, $type, $witherrors) = @_;
    
    my($offset)=tell($output)+1;
    my(@errs)=(); @errs=("uw","ue") if ($witherrors);
    my(@buffer)=("\n");
        
    my($val, @continuations, $margin);
    
    #
    # If we have an unknown object, let's try
    # and print this anyway to inform the user ...

    if ((!$type) || ($object{"ue"})) {

       my(@keys)=();
       my(%doubles)=();

       @keys=split(/ /, $OBJATSQ{$type}) if ($type);
       push(@keys, grep( ! /^u[ew]$/, keys %object), @errs);
       
       foreach $key (@keys) {
            
          next if ((!defined($object{$key})) ||
                   ($doubles{$key}) ||
                   ($key=~ /$CONTINUATIONSUFFIX$/o) || 
                   ((!$witherrors) && ($key=~ /^u[ew]$/)));
 
          $doubles{$key}=1;
          
          foreach $val (split(/\n/, $object{$key})) {
               
             if ($ATTL{$key}) {
                push(@buffer, $ATTL{$key}, ": ", " " x ($MAXATTRIBUTELENGTH - length($ATTL{$key})));
             }
             else {
                push(@buffer, $key, ": ");
             }

             #
             # for just in case:
             # remove any line continuations at the end of lines ...

             #
             # we will not enter 'foreach' when $val=""
             # so we are repairing it in advance ...

             push(@buffer, "\n") if ($val eq "");

             $val=~ s/[^\S\n]+$//;

             #
             # add line continuation leading spaces

             @continuations=split(/ /, $object{$key.$CONTINUATIONSUFFIX});

             foreach (split(/(\r)/, $val)) {
                  
                if ($_ eq "\r") {

                   $margin=shift(@continuations);
                   $margin=2 if ((!$margin) || ($margin<2));

                   push(@buffer, (" " x ($MAXATTRIBUTELENGTH + $margin)));

                }
                elsif (scalar(@buffer)>$MAXLISTLENGTH) {
                   die("in enwrite: cannot write. code: $!") if (!print $output @buffer);
                   @buffer=($_, "\n");
                }
                else {
                   push(@buffer, $_, "\n");
                }

             }

          }
        
       }

       die("in enwrite: cannot write. code: $!") if ((@buffer) && (!print $output @buffer));
       return $offset;
    
    }
    
    foreach $key (split(/ /, $OBJATSQ{$type}), @errs) {
       
       next if (!defined($object{$key}));

       my @vals = split(/\n/, $object{$key});

       # if this is an empty attribute, but we still want to output it,
       # do so here
       if ((@vals == 0) && !$REMOVE_EMPTY) {
          push(@vals, '');
       }


       # print STDERR "*",$key,"* ", $object{$key}, "\n";
    
       foreach $val (@vals) {

          push(@buffer, $ATTL{$key}, ": ", " " x ($MAXATTRIBUTELENGTH - length($ATTL{$key})));

          #
          # for just in case:
          # remove any line continuations at the end of lines ...

          $val=~ s/[^\S\n]+$//;

          #
          # we will not enter 'foreach' when $val=""
          # so we are repairing it in advance ...

          push(@buffer, "\n") if ($val eq "");

          #
          # add line continuation leading spaces

          @continuations=split(/ /, $object{$key.$CONTINUATIONSUFFIX});

          foreach (split(/(\r)/, $val)) {

             if ($_ eq "\r") {

                $margin=shift(@continuations);
                $margin=2 if ((!$margin) || ($margin<2));

                push(@buffer, (" " x ($MAXATTRIBUTELENGTH + $margin)));

             }
             elsif (scalar(@buffer)>$MAXLISTLENGTH) {
                die("in enwrite: cannot write. code: $!") if (!print $output @buffer);
                @buffer=($_, "\n");
             }
             else {
                push(@buffer, $_, "\n");
             }

          }

       }

    }

    die("in enwrite: cannot write. code: $!") if ((@buffer) && (!print $output @buffer));

    return $offset;
    
}

1;

#
#       End of included 'enwrite.pl' data is here
#

#
#       'convert2domainname' is included from the file 'misc.pl'
#


#       misc - miscellaneaous functions
#
#       $RCSfile: ripe2rpsl,v $
#       $Revision: 1.1 $
#       $Author: andrei $
#       $Date: 2001/09/13 11:04:09 $
#


sub convert2domainname {
    my($domain)=@_;

    $domain=(gethostbyaddr(pack("C4", split(/\./, $domain)), PF_INET))[0] if ($domain=~ /^$VALIDFULLIP4$/o);
       
    return "" if (!&isdomname($domain));
    return $domain;

}

#
#       End of included 'misc.pl' data is here
#

#
#       'getYYYYMMDDandHHMMSS' is included from the file 'misc.pl'
#


#       misc - miscellaneaous functions
#
#       $RCSfile: ripe2rpsl,v $
#       $Revision: 1.1 $
#       $Author: andrei $
#       $Date: 2001/09/13 11:04:09 $
#


#
# the name says all ...:


sub getYYYYMMDDandHHMMSS {

    my($s,$m,$h,$day,$month,$year,$wd,$yd,$is)=localtime(time);

    $year+=1900;

    my($YYYYMMDD)=sprintf("%4d%2d%2d",$year,++$month,$day);
    $YYYYMMDD=~ tr/ /0/;

    my($HHMMSS)=sprintf("%2d:%2d:%2d",$h,$m,$s);
    $HHMMSS=~ s/ /0/g;

    return ($YYYYMMDD,$HHMMSS);

}

#
#       End of included 'misc.pl' data is here
#

#
#       'isdomname' is included from the file 'misc.pl'
#


#       misc - miscellaneaous functions
#
#       $RCSfile: ripe2rpsl,v $
#       $Revision: 1.1 $
#       $Author: andrei $
#       $Date: 2001/09/13 11:04:09 $
#


sub isdomname {

    return scalar($_[0]=~ /^\s*$DOMAINNAME\s*$/o);

}

# tries to parse the text object as a RIPE-181 object
# returns the type, plus a hash filled with the attributes
# return '' if it is invalid
sub ripe_parse {
    my ($object, $entry, $password) = @_;

    # clear our passed values
    %{$entry} = ();
    ${$password} = undef;

    # type of object encountered
    my $type;

    # valid attributes for object
    my %valid_attr;

    # check each line is of the form:
    #   attribute: value
    my @lines = split(/\n/, $object);
    foreach my $line (@lines) {
        unless ($line =~ /^\s*\*?([a-z0-9\-]+)\s*:\s*(.*)$/i) {
	    return "";
	}
        my ($attr, $val) = ($1, $2);

	# exit if we don't have a proper line
	return "" unless (defined $attr);

	# extract passwords that appear
	if ($attr =~ /^password$/i) {
	    # only return the first password found
	    unless (${$password}) {
	        $line =~ s/^\s+//;
	        ${$password} = $line;
	    }
	    next;
        }

	# figure out the shorthand for this attribute
	$attr = $ATTR{lc($attr)};

	# verify we have a valid shorthand
	return "" unless (defined $attr);

	# save type if necessary
	unless ($type) {
	    my $obj_attr_text = $OBJATSQ{$attr};
	    return "" unless (defined $obj_attr_text);
	    $type = $attr;

	    # fill the %valid_attr hash based on our allowed attributes
	    my @valid_attrs = split(/\s+/, $obj_attr_text);
	    @valid_attr{@valid_attrs} = ();
	}

	# verify this is a valid attribute
	return "" unless (exists $valid_attr{$attr});

	# add value to our hash
	if (exists $entry->{$attr}) {
	    $entry->{$attr} .= "\n$val";
	} else {
	    $entry->{$attr} = $val;
	}
    }

    # return our type
    return $type;
}

#
#       End of included 'misc.pl' data is here
#

#
# end of included code

use English;
use Getopt::Std;

# get any options passed
my %opts;
my $getopts_result = getopts('afimpr', \%opts);
if ($opts{a}) {
    $CONVERT_AS_NAME = 0;
}
if ($opts{f}) {
    $FIX_MISSING = 0;
}
if ($opts{i}) {
    $WARN_INVALID_MNTNER = 0;
}
if ($opts{m}) {
    $USE_MULTILINE = 1;
}
if ($opts{p}) {
    $PROTECT_AUT_NUM = 0;
}
if ($opts{r}) {
    $REMOVE_EMPTY = 0;
}

# output help if invalid options passed
unless ($getopts_result && (@ARGV == 0)) {
    print STDERR <<usage;
Syntax: $PROGRAM_NAME [-a] [-i] [-m] [-p] [-r]

   -a  do not convert '-' to '_' in AS names
   -f  do not fix missing attributes (can result in invalid RPSL)
   -i  do not add a comment warning about invalid maintainer names
   -m  convert multiple attributes to a single continued attribute
   -p  do not protect aut-num objects without maintainers
   -r  do not remove empty attributes
usage
    exit(1);
}

# removed 2001-01-08 by shane in preparation for production use
#($DATE,$TIME)=&getYYYYMMDDandHHMMSS();
#$REMARKSLINE="This object is automatically converted from the RIPE181 registry";
#$CHANGEDLINE=$AUTOBOX." ".$DATE."\n";

local $INPUT_RECORD_SEPARATOR = "";

# read each object
while (defined(my $object = <STDIN>)) {

  # remove our separator
  my $extra_nl = chomp($object);

  # try to parse the object into a nice hash
  local %entry;
  my $password;
  my $type = ripe_parse($object, \%entry, \$password);

  if ($type) {
      # print password, if any
      print $password, "\n" if ($password);

      # don't output withdrawn routes
      next if (( $type eq "rt" ) && $entry{"wd"} );

      # convert and output
      $type=&ripe2rpsl(*entry, $type, 0);
      &enwrite(STDOUT, *entry, $type, 1);

      # separate each object
      print STDOUT "\n";

  } else {
     # if it's not a valid RIPE-181 object, output unchanged except for
     # removal of whitespace at the beginning of lines
     $object =~ s/\n\s+/\n/g;
     $object =~ s/^\s+//;

     print $object;
     print "\n" x $extra_nl;
  }

}

# end of program

__END__
while ($type=(&enread(STDIN, *entry, -1))[0]) {

  # don't output withdrawn routes
  next if (( $type eq "rt" ) && $entry{"wd"} );

  # convert and output
  $type=&ripe2rpsl(*entry, $type, 0);
  &enwrite(STDOUT, *entry, $type, 1);

  # separate each object
  print STDOUT "\n";

}

# end of program
