#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define CSV_LINE_MAX 128 /** maximum charactors per line **/
#define MAX_LINES 66 /** maximum lines of CSV file(1..66) **/
#define COLUMUN_DATE 28
#define COLUMUN_VERSION 55
#define FILTER_RULE_FILE_NAME "/export/http/import/iPASOLINK-filter.csv"
const char ccMTYPE[ ] = "iPASOLINK UX" ;
const char ccKIND[ ] = "Filtering Rule" ;
const char ccLINE2[ ] = "Rule ID" ;
typedef struct { /** CSVファイルから読み込んだFilter Rule **/
unsigned char ucExportTime[ 26 ] ;
unsigned char ucFVersion[ 8 ] ;
struct {
int iRuleID;
int iSourcePort;
int iAction;
int iFilterType;
int iTagMask;
int iVlanID;
int iMacAddressMask;
unsigned char cMacAddress[ 17 ] ; /** xx:xx:xx:xx:xx:xx **/
unsigned char dummy;
} stFilterRules[ MAX_LINES- 2 ] ; /** 64record maximum **/
} FilterDataFmt;
FilterDataFmt FilterRule;
/**************************************************************************
*
* read from CSV file (Filter Rules defined)
*
* return: 0:OK,
* -1:NG(no file, file format error)
*
**************************************************************************/
int LoadFilterRuleFile( FilterDataFmt * Save_p )
{
char * cRet;
int iRet, iLine;
int i;
FILE * File_h; /** file handle **/
char ucBuff[ CSV_LINE_MAX] ; /** temporary data buffer from CSV file **/
char * ary[ 8 ] ; /** for after 3line CSV **/
const int dTbl[ ] = { 2 , 5 , 8 , 11 , 14 } ; /** ":"/"-"charactor offset within MAC address **/
const int nTbl[ ] = { 0 , 3 , 6 , 9 , 12 , 15 } ; /** Hex data of octet **/
File_h
= fopen ( FILTER_RULE_FILE_NAME
, "r" ) ; /** Open CSV file **/ if ( File_h == NULL ) {
/** file not found */
return - 1 ;
}
iRet = 0 ;
for ( iLine = 0 ; iLine < MAX_LINES; iLine++ ) {
cRet
= fgets ( ucBuff
, CSV_LINE_MAX
, File_h
) ; /** read 1 line from CSV file **/ if ( cRet == NULL) { /** EOF **/
if ( iLine < 3 ) {
iRet = - 1 ; /** CSV file format error **/
}
else {
iRet = 0 ; /** read from CSV file complete **/
}
iLine = MAX_LINES; /** end of "for loop" **/
}
switch ( iLine ) {
case 0 : /** 1st line **/
/** check ',' charactor **/
if ( ( strncmp ( ucBuff
, ccMTYPE
, strlen ( ccMTYPE
) ) != 0 ) || ( ucBuff
[ 12 ] != ',' ) || ( strncmp ( & ucBuff
[ 13 ] , ccKIND
, strlen ( ccKIND
) ) != 0 ) || ( ucBuff
[ 27 ] != ',' ) || ( ucBuff
[ 54 ] != ',' ) ) { iLine = MAX_LINES;
iRet = - 1 ; /** NG - CSV file format error **/
}
else { /** format ok **/
/** copy last export date & time **/
memcpy ( Save_p
-> ucExportTime
, & ucBuff
[ COLUMUN_DATE
] , sizeof ( Save_p
-> ucExportTime
) ) ; memcpy ( Save_p
-> ucFVersion
, & ucBuff
[ COLUMUN_VERSION
] , sizeof ( Save_p
-> ucFVersion
) ) ; }
break ;
case 1 : /** 2nd line **/
if ( strncmp ( ucBuff
, ccLINE2
, strlen ( ccLINE2
) ) != 0 ) { /** NG - format error **/ iLine = MAX_LINES;
iRet = - 1 ;
}
break ;
case MAX_LINES: /** error or EOF **/
break ;
default : /** from 3rd to last line **/
ary
[ 0 ] = strtok ( ucBuff
, "," ) ; /** Rule ID(「1~100」であること) **/ Save_p
-> stFilterRules
[ iLine
] .
iRuleID = atoi ( ary
[ 0 ] ) ; if ( ( Save_p-> stFilterRules[ iLine] .iRuleID < 1 ) || ( Save_p-> stFilterRules[ iLine] .iRuleID > 100 ) ) {
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
ary
[ 1 ] = strtok ( NULL
, "," ) ; /** Source Port(「1~4」であること) **/ Save_p
-> stFilterRules
[ iLine
] .
iSourcePort = atoi ( ary
[ 1 ] ) ; if ( ( Save_p-> stFilterRules[ iLine] .iSourcePort < 1 ) || ( Save_p-> stFilterRules[ iLine] .iSourcePort > 4 ) ) {
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
ary
[ 2 ] = strtok ( NULL
, "," ) ; /** Action(「1~2」であること) **/ Save_p
-> stFilterRules
[ iLine
] .
iAction = atoi ( ary
[ 2 ] ) ; if ( ( Save_p-> stFilterRules[ iLine] .iAction < 1 ) || ( Save_p-> stFilterRules[ iLine] .iAction > 2 ) ) {
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
ary
[ 3 ] = strtok ( NULL
, "," ) ; /** Filter Type(「1」であること) **/ Save_p
-> stFilterRules
[ iLine
] .
iFilterType = atoi ( ary
[ 3 ] ) ; if ( Save_p-> stFilterRules[ iLine] .iFilterType != 1 ) {
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
ary
[ 4 ] = strtok ( NULL
, "," ) ; /** VLAN Tag Mask(「1~3」であること) **/ Save_p
-> stFilterRules
[ iLine
] .
iTagMask = atoi ( ary
[ 4 ] ) ; if ( ( Save_p-> stFilterRules[ iLine] .iTagMask < 1 ) || ( Save_p-> stFilterRules[ iLine] .iTagMask > 3 ) ) {
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
ary
[ 5 ] = strtok ( NULL
, "," ) ; /** VLAN ID(「1~4094」であること) **/ Save_p
-> stFilterRules
[ iLine
] .
iVlanID = atoi ( ary
[ 5 ] ) ; if ( ( Save_p-> stFilterRules[ iLine] .iVlanID < 1 ) || ( Save_p-> stFilterRules[ iLine] .iVlanID > 4094 ) ) {
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
ary
[ 6 ] = strtok ( NULL
, "," ) ; /** Source MAC Address Mask(「1~2」であること)**/ Save_p
-> stFilterRules
[ iLine
] .
iMacAddressMask = atoi ( ary
[ 6 ] ) ; if ( ( Save_p-> stFilterRules[ iLine] .iMacAddressMask < 1 ) || ( Save_p-> stFilterRules[ iLine] .iMacAddressMask > 2 ) ) {
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
ary
[ 7 ] = strtok ( NULL
, "," ) ; /** Source MAC Address(MAC Address形式であること)**/ strcpy ( Save_p
-> stFilterRules
[ iLine
] .
cMacAddress , ary
[ 7 ] ) ; for ( i = 0 ; i < sizeof ( dTbl) ; i++ ) {
if ( ( isxdigit ( ( int ) Save_p
-> stFilterRules
[ iLine
] .
cMacAddress [ nTbl
[ i
] ] ) != 0 ) || ( isxdigit ( ( int ) Save_p
-> stFilterRules
[ iLine
] .
cMacAddress [ nTbl
[ i
+ 1 ] ] ) != 0 ) ) { /** charactor is not hexdecimal digit **/
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
if ( ( Save_p-> stFilterRules[ iLine] .cMacAddress [ dTbl[ i] ] != ":" ) &&
( Save_p-> stFilterRules[ iLine] .cMacAddress [ dTbl[ i] ] != "-" ) ) {
/** delimitter is not MAC address format **/
iLine = MAX_LINES;
iRet = - 1 ;
break ;
}
}
break ;
} /** end of switch **/
} /** enf of for loop **/
return iRet;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPiAKI2luY2x1ZGUgPGN0eXBlLmg+CgojZGVmaW5lIENTVl9MSU5FX01BWAkxMjgJCQkJCQkJCQkJCQkvKiogbWF4aW11bSBjaGFyYWN0b3JzIHBlciBsaW5lCQkJCQkqKi8KI2RlZmluZSBNQVhfTElORVMJCTY2CQkJCQkJCQkJCQkJLyoqIG1heGltdW0gbGluZXMgb2YgQ1NWIGZpbGUoMS4uNjYpCQkJKiovCiNkZWZpbmUgQ09MVU1VTl9EQVRFCTI4CiNkZWZpbmUgQ09MVU1VTl9WRVJTSU9OCTU1CiNkZWZpbmUgRklMVEVSX1JVTEVfRklMRV9OQU1FICIvZXhwb3J0L2h0dHAvaW1wb3J0L2lQQVNPTElOSy1maWx0ZXIuY3N2IgoKY29uc3QgY2hhciBjY01UWVBFW10gPSAiaVBBU09MSU5LIFVYIjsKY29uc3QgY2hhciBjY0tJTkRbXSA9ICJGaWx0ZXJpbmcgUnVsZSI7CmNvbnN0IGNoYXIgY2NMSU5FMltdID0gIlJ1bGUgSUQiOwoKdHlwZWRlZiBzdHJ1Y3QgewkJCQkJCQkJCQkJCQkJCQkvKiogQ1NW44OV44Kh44Kk44Or44GL44KJ6Kqt44G/6L6844KT44GgRmlsdGVyIFJ1bGUJCSoqLwoJdW5zaWduZWQgY2hhciB1Y0V4cG9ydFRpbWVbMjZdOwoJdW5zaWduZWQgY2hhciB1Y0ZWZXJzaW9uWzhdOwoJc3RydWN0IHsKCQlpbnQgaVJ1bGVJRDsKCQlpbnQgaVNvdXJjZVBvcnQ7CgkJaW50IGlBY3Rpb247CgkJaW50IGlGaWx0ZXJUeXBlOwoJCWludCBpVGFnTWFzazsKCQlpbnQgaVZsYW5JRDsKCQlpbnQgaU1hY0FkZHJlc3NNYXNrOwoJCXVuc2lnbmVkIGNoYXIgY01hY0FkZHJlc3NbMTddOwkJCQkJCQkJCS8qKiB4eDp4eDp4eDp4eDp4eDp4eAkJCQkJCQkqKi8KCQl1bnNpZ25lZCBjaGFyIGR1bW15OwoJfSBzdEZpbHRlclJ1bGVzW01BWF9MSU5FUy0yXTsJCQkJCQkJCQkJLyoqIDY0cmVjb3JkIG1heGltdW0JCQkJCQkJKiovCn0gRmlsdGVyRGF0YUZtdDsKCkZpbHRlckRhdGFGbXQgRmlsdGVyUnVsZTsKCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqCioJcmVhZCBmcm9tIENTViBmaWxlIChGaWx0ZXIgUnVsZXMgZGVmaW5lZCkKKgoqCXJldHVybjoJIDA6T0ssCioJCQktMTpORyhubyBmaWxlLCBmaWxlIGZvcm1hdCBlcnJvcikKKgoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KaW50IExvYWRGaWx0ZXJSdWxlRmlsZSggRmlsdGVyRGF0YUZtdCAqU2F2ZV9wICkKewpjaGFyICpjUmV0OwppbnQgaVJldCxpTGluZTsKaW50IGk7CkZJTEUgKkZpbGVfaDsJCQkJCQkJCQkJCQkJCQkvKiogZmlsZSBoYW5kbGUJCQkJCQkJCQkqKi8KY2hhciB1Y0J1ZmZbQ1NWX0xJTkVfTUFYXTsJCQkJCQkJCQkJCQkvKiogdGVtcG9yYXJ5IGRhdGEgYnVmZmVyIGZyb20gQ1NWIGZpbGUJCQkqKi8KY2hhciAqYXJ5WzhdOwkJCQkJCQkJCQkJCQkJCS8qKiBmb3IgYWZ0ZXIgM2xpbmUgQ1NWCQkJCQkJCSoqLwpjb25zdCBpbnQgZFRibFtdID0geyAyLDUsOCwxMSwxNCB9OwkJCQkJCQkJCQkvKiogIjoiLyItImNoYXJhY3RvciBvZmZzZXQgd2l0aGluIE1BQyBhZGRyZXNzCSoqLwpjb25zdCBpbnQgblRibFtdID0geyAwLDMsNiw5LDEyLDE1IH07CQkJCQkJCQkJLyoqIEhleCBkYXRhIG9mIG9jdGV0CQkJCQkJCSoqLwoKCUZpbGVfaCA9IGZvcGVuKCBGSUxURVJfUlVMRV9GSUxFX05BTUUsICJyIiApOwkJCQkJCS8qKiBPcGVuIENTViBmaWxlCQkJCQkJCQkqKi8KCWlmKCBGaWxlX2ggPT0gTlVMTCApIHsKCQkvKiogZmlsZSBub3QgZm91bmQJCQkqLwoJCXJldHVybiAtMTsKCX0KCglpUmV0ID0gMDsKCWZvciggaUxpbmUgPSAwOyBpTGluZSA8IE1BWF9MSU5FUzsgaUxpbmUrKyApIHsKCQljUmV0ID0gZmdldHMoIHVjQnVmZiwgQ1NWX0xJTkVfTUFYLCBGaWxlX2ggKTsJCQkJCS8qKiByZWFkIDEgbGluZSBmcm9tIENTViBmaWxlCQkJCQkqKi8KCQlpZihjUmV0ID09IE5VTEwpCXsJCQkJCQkJCQkJCS8qKiBFT0YJCQkJCQkJCQkJCSoqLwoJCQlpZiggaUxpbmUgPCAzICkgewoJCQkJaVJldCA9IC0xOwkJCQkJCQkJCQkJCS8qKiBDU1YgZmlsZSBmb3JtYXQgZXJyb3IJCQkJCQkqKi8KCQkJfQoJCQllbHNlIHsKCQkJCWlSZXQgPSAwOwkJCQkJCQkJCQkJCS8qKiByZWFkIGZyb20gQ1NWIGZpbGUgY29tcGxldGUJCQkJCSoqLwoJCQl9CgkJCWlMaW5lID0gTUFYX0xJTkVTOwkJCQkJCQkJCQkJLyoqIGVuZCBvZiAiZm9yIGxvb3AiCQkJCQkJCSoqLwoJCX0KCQlzd2l0Y2goIGlMaW5lICkgewoJCQljYXNlIDA6CQkvKiogMXN0IGxpbmUJCQkJKiovCgkJCQkvKiogY2hlY2sgJywnIGNoYXJhY3RvcgkJCQkqKi8KCQkJCWlmKCggc3RybmNtcCggdWNCdWZmLCBjY01UWVBFLCBzdHJsZW4oY2NNVFlQRSkgKSAhPSAwICkgfHwgKCB1Y0J1ZmZbMTJdICE9ICcsJykgfHwKCQkJCSAgICggc3RybmNtcCggJnVjQnVmZlsxM10sIGNjS0lORCwgc3RybGVuKGNjS0lORCkgKSAhPSAwICkgfHwgKCB1Y0J1ZmZbMjddICE9ICcsJyApIHx8ICggdWNCdWZmWzU0XSAhPSAnLCcgKSkgewoJCQkJCWlMaW5lID0gTUFYX0xJTkVTOwoJCQkJCWlSZXQgPSAtMTsJCQkJCQkJCQkJCS8qKiBORyAtIENTViBmaWxlIGZvcm1hdCBlcnJvcgkJCQkJKiovCgkJCQl9CgkJCQllbHNlIHsJCQkJCQkJCQkJCQkJLyoqIGZvcm1hdCBvawkJCQkJCQkJCSoqLwoJCQkJCS8qKiBjb3B5IGxhc3QgZXhwb3J0IGRhdGUgJiB0aW1lCQkqKi8KCQkJCQltZW1jcHkoIFNhdmVfcC0+dWNFeHBvcnRUaW1lLCAmdWNCdWZmW0NPTFVNVU5fREFURV0sIHNpemVvZihTYXZlX3AtPnVjRXhwb3J0VGltZSkgKTsKCQkJCQltZW1jcHkoIFNhdmVfcC0+dWNGVmVyc2lvbiwgJnVjQnVmZltDT0xVTVVOX1ZFUlNJT05dLCBzaXplb2YoU2F2ZV9wLT51Y0ZWZXJzaW9uKSApOwoJCQkJfQoJCQkJYnJlYWs7CgkJCWNhc2UgMToJCS8qKiAybmQgbGluZQkJCQkqKi8KCQkJCWlmKCBzdHJuY21wKCB1Y0J1ZmYsIGNjTElORTIsIHN0cmxlbihjY0xJTkUyKSApICE9IDAgKSB7LyoqIE5HIC0gZm9ybWF0IGVycm9yCQkJCQkJCSoqLwoJCQkJCWlMaW5lID0gTUFYX0xJTkVTOwoJCQkJCWlSZXQgPSAtMTsKCQkJCX0KCQkJCWJyZWFrOwoJCQljYXNlIE1BWF9MSU5FUzoJCQkJCQkJCQkJCQkvKiogZXJyb3Igb3IgRU9GCQkJCQkJCQkqKi8KCQkJCWJyZWFrOwoJCQlkZWZhdWx0OgkvKiogZnJvbSAzcmQgdG8gbGFzdCBsaW5lCSoqLwoJCQkJYXJ5WzBdID0gc3RydG9rKCB1Y0J1ZmYsICIsIiApOwkJCQkJCQkvKiogUnVsZSBJRO+8iOOAjDHvvZ4xMDDjgI3jgafjgYLjgovjgZPjgajvvIkJCQkJKiovCgkJCQlTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlSdWxlSUQgPSBhdG9pKCBhcnlbMF0gKTsKCQkJCWlmKCggU2F2ZV9wLT5zdEZpbHRlclJ1bGVzW2lMaW5lXS5pUnVsZUlEIDwgMSApIHx8ICggU2F2ZV9wLT5zdEZpbHRlclJ1bGVzW2lMaW5lXS5pUnVsZUlEID4gMTAwICkpIHsKCQkJCQlpTGluZSA9IE1BWF9MSU5FUzsKCQkJCQlpUmV0ID0gLTE7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCQlhcnlbMV0gPSBzdHJ0b2soIE5VTEwsICIsIiApOwkJCQkJCQkvKiogU291cmNlIFBvcnTvvIjjgIwx772eNOOAjeOBp+OBguOCi+OBk+OBqO+8iQkJCSoqLwoJCQkJU2F2ZV9wLT5zdEZpbHRlclJ1bGVzW2lMaW5lXS5pU291cmNlUG9ydCA9IGF0b2koIGFyeVsxXSApOwoJCQkJaWYoKCBTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlTb3VyY2VQb3J0IDwgMSApIHx8ICggU2F2ZV9wLT5zdEZpbHRlclJ1bGVzW2lMaW5lXS5pU291cmNlUG9ydCA+IDQgKSkgewoJCQkJCWlMaW5lID0gTUFYX0xJTkVTOwoJCQkJCWlSZXQgPSAtMTsKCQkJCQlicmVhazsKCQkJCX0KCQkJCWFyeVsyXSA9IHN0cnRvayggTlVMTCwgIiwiICk7CQkJCQkJCS8qKiBBY3Rpb27vvIjjgIwx772eMuOAjeOBp+OBguOCi+OBk+OBqO+8iQkJCQkqKi8KCQkJCVNhdmVfcC0+c3RGaWx0ZXJSdWxlc1tpTGluZV0uaUFjdGlvbiA9IGF0b2koIGFyeVsyXSApOwoJCQkJaWYoKCBTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlBY3Rpb24gPCAxICkgfHwgKCBTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlBY3Rpb24gPiAyICkpIHsKCQkJCQlpTGluZSA9IE1BWF9MSU5FUzsKCQkJCQlpUmV0ID0gLTE7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCQlhcnlbM10gPSBzdHJ0b2soIE5VTEwsICIsIiApOwkJCQkJCQkvKiogRmlsdGVyIFR5cGXvvIjjgIwx44CN44Gn44GC44KL44GT44Go77yJCQkJCSoqLwoJCQkJU2F2ZV9wLT5zdEZpbHRlclJ1bGVzW2lMaW5lXS5pRmlsdGVyVHlwZSA9IGF0b2koIGFyeVszXSApOwoJCQkJaWYoIFNhdmVfcC0+c3RGaWx0ZXJSdWxlc1tpTGluZV0uaUZpbHRlclR5cGUgIT0gMSApIHsKCQkJCQlpTGluZSA9IE1BWF9MSU5FUzsKCQkJCQlpUmV0ID0gLTE7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCQlhcnlbNF0gPSBzdHJ0b2soIE5VTEwsICIsIiApOwkJCQkJCQkvKiogVkxBTiBUYWcgTWFza++8iOOAjDHvvZ4z44CN44Gn44GC44KL44GT44Go77yJCQkJKiovCgkJCQlTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlUYWdNYXNrID0gYXRvaSggYXJ5WzRdICk7CgkJCQlpZigoIFNhdmVfcC0+c3RGaWx0ZXJSdWxlc1tpTGluZV0uaVRhZ01hc2sgPCAxICkgfHwgKCBTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlUYWdNYXNrID4gMyApKSB7CgkJCQkJaUxpbmUgPSBNQVhfTElORVM7CgkJCQkJaVJldCA9IC0xOwoJCQkJCWJyZWFrOwoJCQkJfQoJCQkJYXJ5WzVdID0gc3RydG9rKCBOVUxMLCAiLCIgKTsJCQkJCQkJLyoqIFZMQU4gSUTvvIjjgIwx772eNDA5NOOAjeOBp+OBguOCi+OBk+OBqO+8iQkJCSoqLwoJCQkJU2F2ZV9wLT5zdEZpbHRlclJ1bGVzW2lMaW5lXS5pVmxhbklEID0gYXRvaSggYXJ5WzVdICk7CgkJCQlpZigoIFNhdmVfcC0+c3RGaWx0ZXJSdWxlc1tpTGluZV0uaVZsYW5JRCA8IDEgKSB8fCAoIFNhdmVfcC0+c3RGaWx0ZXJSdWxlc1tpTGluZV0uaVZsYW5JRCA+IDQwOTQgKSkgewoJCQkJCWlMaW5lID0gTUFYX0xJTkVTOwoJCQkJCWlSZXQgPSAtMTsKCQkJCQlicmVhazsKCQkJCX0KCQkJCWFyeVs2XSA9IHN0cnRvayggTlVMTCwgIiwiICk7CQkJCQkJCS8qKiBTb3VyY2UgTUFDIEFkZHJlc3MgTWFza++8iOOAjDHvvZ4y44CN44Gn44GC44KL44GT44Go77yJKiovCgkJCQlTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlNYWNBZGRyZXNzTWFzayA9IGF0b2koIGFyeVs2XSApOwoJCQkJaWYoKCBTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmlNYWNBZGRyZXNzTWFzayA8IDEgKSB8fCAoIFNhdmVfcC0+c3RGaWx0ZXJSdWxlc1tpTGluZV0uaU1hY0FkZHJlc3NNYXNrID4gMiApKSB7CgkJCQkJaUxpbmUgPSBNQVhfTElORVM7CgkJCQkJaVJldCA9IC0xOwoJCQkJCWJyZWFrOwoJCQkJfQoJCQkJYXJ5WzddID0gc3RydG9rKCBOVUxMLCAiLCIgKTsJCQkJCQkJLyoqIFNvdXJjZSBNQUMgQWRkcmVzc++8iE1BQyBBZGRyZXNz5b2i5byP44Gn44GC44KL44GT44Go77yJKiovCgkJCQlzdHJjcHkoIFNhdmVfcC0+c3RGaWx0ZXJSdWxlc1tpTGluZV0uY01hY0FkZHJlc3MsIGFyeVs3XSApOwoJCQkJZm9yKCBpID0gMDsgaSA8IHNpemVvZihkVGJsKTsgaSsrICkgewoJCQkJCWlmKCggaXN4ZGlnaXQoIChpbnQpU2F2ZV9wLT5zdEZpbHRlclJ1bGVzW2lMaW5lXS5jTWFjQWRkcmVzc1tuVGJsW2ldXSkgIT0gMCApIHx8CgkJCQkJICAgKCBpc3hkaWdpdCggKGludClTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmNNYWNBZGRyZXNzW25UYmxbaSsxXV0pICE9IDAgKSkgewoJCQkJCQkvKiogY2hhcmFjdG9yIGlzIG5vdCBoZXhkZWNpbWFsIGRpZ2l0CQkJCSoqLwoJCQkJCQlpTGluZSA9IE1BWF9MSU5FUzsKCQkJCQkJaVJldCA9IC0xOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQkJaWYoKCBTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmNNYWNBZGRyZXNzW2RUYmxbaV1dICE9ICI6IiApICYmCgkJCQkJICAgKCBTYXZlX3AtPnN0RmlsdGVyUnVsZXNbaUxpbmVdLmNNYWNBZGRyZXNzW2RUYmxbaV1dICE9ICItIiApKSB7CgkJCQkJCS8qKiBkZWxpbWl0dGVyIGlzIG5vdCBNQUMgYWRkcmVzcyBmb3JtYXQJCQkqKi8KCQkJCQkJaUxpbmUgPSBNQVhfTElORVM7CgkJCQkJCWlSZXQgPSAtMTsKCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJfQoJCQkJYnJlYWs7CgkJfSAvKiogZW5kIG9mIHN3aXRjaAkJKiovCgl9LyoqIGVuZiBvZiBmb3IgbG9vcAkqKi8KCglmY2xvc2UoIEZpbGVfaCApOwoJcmV0dXJuIGlSZXQ7Cgp9Cg==