//SCRIPT INFO: (* ========================================================================================== Following until 'SCRIPT BEGINS HERE...' is documentation. Please see 'USER OPTIONS' in the body of the script. --------------------------------------------- SCRIPT: FilmAffinity_[ES]' CO-AUTHORS: VVV --------------------------------------------- CHANGE LOG (22/11/2015): V 0.2.1.3 VVV: Writes 'ratingValue'=orating with point english separator for better standarisation. Eliminate "2014" from name. V 0.2.1.2 VVV: Adjust to new API ('Año'=year,'ratingValue'=orating,'ratingCount'=FilmAffinity_Votes,'Director'=Directors) Only direct Movies: Don't work the list in "Advanced Search" because now it's a Google script. V 0.2.1.1 Add BYPASS_SILENT = False; //Set to True to ensure ShowMessage alerts (then bypass Silent PVdB preferences) V 0.2.1.0 VVV: Adjust WEB_SPECIFIC to new API (AKA Bouton). V 0.2.0.2 VVV: Fixed bug with movie first search and download (Ivek23 detected) V 0.2.0.1 VVV: Add (needs Custom Field ~FilmAffinity_Votes~) for 'votos' (Ivek23 proposition) V 0.2.0.0 VVV: Rebuild script. v 0.1.4.2 VVV: Adjust WEB_SPECIFIC to new API. v 0.1.4.1 VVV: Erase final Slash in BASE_URL. v 0.1.4.0 VVV: Officialized Ivek23 modify for the year problem. v 0.1.3.0 VVV: Roundabout for the spanish letter of "
Año
". Some user see as "
Ano
" v 0.1.2.0 VVV: Corrections: Duration (field name and length in seconds),genres (movies without category), Improvements: RemoveTags (Simplify the Web delimitators choice) v 0.1.1.0 VVV: Minor corrections and improvements v 0.1.0.0 VVV: initial "public" release --------------------------------------------- FIELD USE: This is a script designed to be easy to understand and to adapt. For this reason may be missing some fields and the programming may not be smart. It's a only "One Pass" Script and get data in WEB SECUENTIAL ORDER. The Personal Video DataBase field names in comments are enclosed in "~" so they are easier to find in the script. The WEB_SPECIFIC commentary points out the specific text for Web fields. Use Log PVdB debug Window for looking search errors. (Due a PVdB "GET" scripts funtions seems doesn't work with 'https' URL de v.0.2.0.0 works with API web dialog. FOOTNOTES: 1.Control the use of standard fields using the "Overwrite Fields" plugin preferences in the main program PVD: Preferences > Plugins > 'Script Name' > Overwrite fields to control how these items are to be updated. 2.Hits for adapt the Script. 2.1. Search WEB_SPECIFIC comentary for adapt the specific Web text of fields. 2.2. Script execution: 0) Get results of "Obligatory callback Functions" 1) GetDownloadURL (Obligatory callback Functions) = This function should return URL that should be downloaded by the main application and then passed to the script’s ParsePage function as text. It may have several modes selon the Script mode (Global Var Mode = smSearch, smNormal, smFinished). 2) ParsePage (Obligatory callback Functions) = This function receives the text of the download web page passed to the main application in the GetDownloadURL function. It has several modes selon the Script mode (Global Var Mode = smSearch, smNormal, smFinished). KNOWN ISSUES: 1. For compiling cuestions functions must be defined in the script before use (not in order of execution). 2. For the search texts for locating the fields in Web page Null '' value it's not valid. You must replaces all escaped HTML characters (like <>&") with normal characters (like <, >,$, "). 3. It's a only "One Pass" Script: It DOES NOT makes several calls to the main program to scrape information from various pages of the movie in the same site. It only do that for searching mode in a movie list results. 4. If desired, you needs Custom Field ~FilmAffinity_Votes~ for storing the number of votes. SCRIPT STRUCTURE: 1.Script data and user options constants 2.Some useful generic constants 3.Global variables 4.Obligatory PVD callback Functions GetScriptVersion, GetScriptName, GetScriptDesc, GetBaseURL, GetScriptLang, GetScriptType, GetCurrentMode, GetDownloadURL. (Note: ParsePage is at the end of the file for compiling cuestions). 5.Optional PVD callback Functions GetRatingName ,GetCodePage, GetDownloadMethod, GetPrefixMode; 6.User Functions an procedures (with their constans): Not used. 7.Obligatory PVD callback function ParsePage (at the end of the file for compiling cuestions) *) //SCRIPT BEGINS HERE... //Some Useful constants const //User Options GET_CREDIT = True; //Set to True to ensure Credits types not added even if 'Overwrite fields' setting allows GET_LENGTH = False; //Set to False to ensure ~Lenght~ not set even if 'Overwrite fields' setting allows BYPASS_SILENT = False; //Set to True to ensure ShowMessage alerts (then bypass Silent PVdB preferences) //Script types stMovies = 0; stPeople = 1; stPoster = 2; //Script data SCRIPT_VERSION = '0.2.1.3'; SCRIPT_NAME = 'FilmAffinity [ES]'; SCRIPT_DESC = '[ES] Get Movie Info from FilmAffinity.com (easy_mod Script)'; SCRIPT_LANG = $0a; //Spanish SCRIPT_TYPE = stMovies; BASE_URL = 'http://www.filmaffinity.com'; //WEB_SPECIFIC RATING_NAME = 'FilmAffinity'; //WEB_SPECIFIC SEARCH_STR = 'http://www.filmaffinity.com/es/search.php?stype=title&stext=%s'; //WEB_SPECIFIC CODE_PAGE = 65001; //Use 0 for Autodetect //Script modes smSearch = 0; smNormal = 1; smCast = 2; smReview = 3; smCredits = 4; smDVDReleases = 5; smPoster = 6; smFinished = 7; //Parse results prError = 0; prFinished = 1; prList = 2; prListImage = 3; prDownload = 4; //Download methods dmGET = 0; dmPOST = 1; //Credits types ctActors = 0; ctDirectors = 1; ctWriters = 2; ctComposers = 3; ctProducers = 4; //Image types itPoster = 0; itScreenShot = 1; itFrontCover = 2; itDiscImage = 3; itPhoto = 4; //Global variables var Mode:Byte; //------------------------------------------------------------------------------ //Obligatory callback Functions //------------------------------------------------------------------------------ function GetScriptVersion:String; begin Result:=SCRIPT_VERSION; end; function GetScriptName:String; begin Result:=SCRIPT_NAME; end; function GetScriptDesc:String; begin Result:=SCRIPT_DESC; end; function GetBaseURL:AnsiString; begin Result:=BASE_URL; end; function GetScriptLang: Cardinal; begin Result:=SCRIPT_LANG; end; function GetScriptType:Byte; begin Result:=SCRIPT_TYPE; end; function GetCurrentMode:Byte; begin Result:=Mode; end; function GetDownloadURL:AnsiString; begin LogMessage('Function GetDownloadURL|'); LogMessage('Global Var-Mode|'+IntToStr(Mode)+'|'); if (Mode=smSearch) then Result:=SEARCH_STR; //Has not movie URL. end; //------------------------------------------------------------------------------ function GetCodePage : Cardinal; begin Result := CODE_PAGE; end; //------------------------------------------------------------------------------ //Obligatory callback Function //------------------------------------------------------------------------------ function ParsePage(HTML:String;URL:AnsiString):Cardinal; var curPos,endPos:Integer; Title,Year,MovieURL,PreviewURL,ItemValue,ItemList:String; begin LogMessage('Function ParsePage|'); LogMessage('Global Var-Mode|'+IntToStr(Mode)+'|'); LogMessage('Local Var-URL|'+URL+'|'); //LogMessage('Local Var-HTML:Begin|'+HTML+'|End'); //HTML:=FileToString('page.html'); //Debugging statement HTML:=HTMLToText(HTML); if (Mode=smSearch) then begin //In search Mode if Pos('Búsqueda avanzada',HTML)>0 then begin //WEB_SPECIFIC if BYPASS_SILENT then ShowMessage('Necesaria busqueda avanzada. Introduzca el URL de la pelicula en el campo manualmente (recordar que se separan por espacios) y repita.','FilmAffinity Search Results'); LogMessage('Búsqueda avanzada|'); Result:=prError; Exit; end; //Ancient code.Don't work the list in because now it's a Google script. if Pos('No hay resultados.',HTML)>0 then begin //WEB_SPECIFIC if BYPASS_SILENT then ShowMessage('No hay resultados','FilmAffinity Search Results'); LogMessage('No hay resultados.|'); Result:=prError; Exit; end; if Pos('resultados por título',HTML)>0 then begin //WEB_SPECIFIC LogMessage(' Severals Movies'); // 'Ver todos' if Pos ('Ver todos',HTML)>0 then begin //WEB_SPECIFIC if BYPASS_SILENT then ShowMessage('Varias páginas de resultados. Sólo se usará la primera. Si no lo encuentra, introduzca el URL de la pelicula en el campo manualmente y repita.','FilmAffinity Search Results'); end; LogMessage('Parsing search Movies results'); curPos:=Pos('resultados por título',HTML); //String which opens the Web Search List data. WEB_SPECIFIC curPos:=PosFrom('
0 do begin LogMessage(' Parsing search movie results in '+IntToStr(curPos)+' ...'); //Get PreviewURL. PreviewURL:=''; curPos:=PosFrom('
',HTML,endPos); //String which opens the Web Result PreviewURL data. WEB_SPECIFIC if curPos>0 then begin curPos:=curPos+Length('
'); //String which opens the Web Result PreviewURL data. WEB_SPECIFIC curPos:=PosFrom('src="',HTML,curPos)+Length('src="'); //String which opens the Web Result PreviewURL text. WEB_SPECIFIC endPos:=PosFrom('" border="0">',HTML,curPos); //String which closes the Web Result PreviewURL text. WEB_SPECIFIC PreviewURL:= Copy(HTML,curPos,endPos - curPos); LogMessage(' Parse Results PreviewURL:'+PreviewURL+'||'); endPos:=endPos+Length('" border="0">'); //String which closes the Web Result PreviewURL text. WEB_SPECIFIC end; //Get MovieURL + Title + Year MovieURL:=''; Title:=''; Year:=''; curPos:=PosFrom('
',HTML,endPos); //String which opens the Web URL+Title+Year data. WEB_SPECIFIC if curPos>0 then begin curPos:=curPos+Length('
'); //String which opens the Web URL+Title+Year data. WEB_SPECIFIC curPos:=PosFrom('',HTML,endPos)+Length('>'); //String which opens the Web Result Title text. WEB_SPECIFIC endPos:=PosFrom(' (',HTML,curPos)+Length('> ('); //String which opens the Web Result Year text. WEB_SPECIFIC endPos:=PosFrom(') ',HTML)+Length('

'); //WEB_SPECIFIC curPos:=PosFrom('',HTML,curPos)+Length(''); //WEB_SPECIFIC endPos:=PosFrom('',HTML,curPos); //WEB_SPECIFIC ItemValue:=Copy(HTML,curPos,endPos-curPos); if Length(ItemValue)=LastPos(' ',ItemValue) then ItemValue:=Copy(ItemValue,1,Length(ItemValue)-1); //WEB_SPECIFIC AddFieldValueXML('title',ItemValue); LogMessage(' Get result title:'+ItemValue+'||'); //"right-column"
//"movie-main-image-container" curPos:=Pos('
',HTML)+Length('
');//WEB_SPECIFIC //Get ~poster~ curPos:=PosFrom('',HTML)+Length('
'); //WEB_SPECIFIC //Get ~orating~ curPos:=PosFrom('',HTML,curPos)+Length('
'); //WEB_SPECIFIC curPos:=Pos('
',HTML,curPos); //WEB_SPECIFIC ItemValue:=Copy(HTML,curPos,endPos-curPos); ItemValue:=StringReplace(ItemValue,',','.',True,True,False); //Decimal comma spanish separator to point english separator. AddFieldValueXML('orname',RATING_NAME); AddFieldValueXML('orating',ItemValue); LogMessage(' Get result orating:'+ItemValue+'||'); //Get Custom Field ~FilmAffinity_Votes~ curPos:=Pos('',HTML,curPos); //WEB_SPECIFIC. ItemValue:=Copy(HTML,curPos,endPos - curPos); ItemValue:=StringReplace(ItemValue,'.','',True,True,False); //Code for eliminate thousands point ItemValue:=StringReplace(ItemValue,',','',True,True,False); //Code for eliminate thousands comma AddCustomFieldValueByName('FilmAffinity_Votes',ItemValue); LogMessage(' Get result Custom Field ~FilmAffinity_Votes~'+ItemValue+'||'); //"left-column"
//Get ~origtitle~ curPos:=Pos('
Título original
',HTML)+Length('
Título original
');//WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); if (0',HTML,curPos)) then begin endPos:=PosFrom('',HTML,curPos); //WEB_SPECIFIC end else begin endPos:=PosFrom('
',HTML,curPos); //WEB_SPECIFIC end; ItemValue:=Copy(HTML,curPos,endPos - curPos); if Length(ItemValue)=LastPos(' ',ItemValue) then ItemValue:=Copy(ItemValue,1,Length(ItemValue)-1); //WEB_SPECIFIC AddFieldValueXML('origtitle',ItemValue); LogMessage(' Get result origtitle:'+ItemValue+'||'); //Get ~year~ //Roundabout for the spanish letter of '
Año
'. Some user see as '
Ano
' HTML:=StringReplace(HTML,'
Ano
','
Año
',True,False,False); curPos:=Pos('
Año
',HTML)+Length('
Año
'); //WEB_SPECIFIC curPos:=PosFrom('',HTML,curPos); //WEB_SPECIFIC ItemValue:=Copy(HTML,curPos,endPos-curPos); AddFieldValueXML('year',ItemValue); //WEB_SPECIFIC. LogMessage(' Get result year:'+ItemValue+'||'); //Get ~lenght~ (User option GET_LENGTH) if GET_LENGTH then begin curPos:=Pos('
Duración
',HTML)+Length('
Duración
'); //WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); //WEB_SPECIFIC endPos:=PosFrom(' min.
',HTML,curPos); //WEB_SPECIFIC ItemValue:=IntToStr(StrToInt(Copy(HTML,curPos,endPos-curPos))*60); //WEB_SPECIFIC AddFieldValueXML('lenght',ItemValue); LogMessage(' Get result lenght:'+ItemValue+'||'); end; //Get ~country~ (several values in a comma separated list)(Only name in Web from !file! list) curPos:=Pos('
País
',HTML)+Length('
País
'); //WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); //WEB_SPECIFIC endPos:=PosFrom('
',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); LogMessage(' Parse results List country:'+ItemList+'||'); curPos:=Pos('title="',ItemList)+Length('title="'); //WEB_SPECIFIC endPos:=PosFrom('">',ItemList,curPos); //WEB_SPECIFIC ItemValue:=Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('title="',ItemList,endPos); //WEB_SPECIFIC While 0',ItemList,curPos); //WEB_SPECIFIC ItemValue:=ItemValue+','+Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('title="',ItemList,endPos); //WEB_SPECIFIC LogMessage(' Parse results country:'+ItemValue+'||'); end; AddFieldValueXML('country',ItemValue); LogMessage(' Get results country:'+ItemValue+'||'); //Get ~Directors~, ~Writers~, ~Composers~, Photographers (Not Implemented in PVDB),~Actors~(Only name in Web) if GET_CREDIT then begin //User option GET_CREDIT //Get ~Directors~ (Only name in Web from !file! list). curPos:=Pos('
Director
',HTML)+Length('
Director
'); //WEB_SPECIFIC curPos:=PosFrom('',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); LogMessage(' Parse results List Directors:'+ItemList+'||'); curPos:=Pos('',ItemList); //WEB_SPECIFIC While 0'); //WEB_SPECIFIC endPos:=PosFrom('',ItemList,curPos); //WEB_SPECIFIC ItemValue:=Copy(ItemList,curPos,endPos-curPos); if 1=Pos(' ',ItemValue) then ItemValue:=Copy(ItemValue,2,Length(ItemValue)-1); //WEB_SPECIFIC AddMoviePerson(ItemValue,'','','',ctDirectors); LogMessage(' Get results Directors:'+ItemValue+'||'); curPos:=PosFrom('',ItemList,endPos); //WEB_SPECIFIC end; //Get ~Writers~ (Only name in Web from !name! list). curPos:=Pos('
Guión
',HTML); //WEB_SPECIFIC if 0Guión'); //WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); //WEB_SPECIFIC endPos:=PosFrom('
',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); LogMessage(' Parse results List Writers:'+ItemList+'||'); curPos:=1; //WEB_SPECIFIC endPos:=PosFrom(', ',ItemList,curPos); //WEB_SPECIFIC if 0=endPos then ItemValue:=Copy(ItemList,curPos,1+Length(ItemList)-curPos); While 0Música',HTML); //WEB_SPECIFIC if 0Música'); //WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); //WEB_SPECIFIC endPos:=PosFrom('
',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); LogMessage(' Parse results List Composers:'+ItemList+'||'); curPos:=1; //WEB_SPECIFIC endPos:=PosFrom(', ',ItemList,curPos); //WEB_SPECIFIC if 0=endPos then ItemValue:=Copy(ItemList,curPos,1+Length(ItemList)-curPos); While 0Fotografía'; //WEB_SPECIFIC // Not Implemented in PVD //Get ~Actors~ (Only name in Web from !file! list) curPos:=Pos('
Reparto
',HTML)+Length('
Reparto
'); //WEB_SPECIFIC curPos:=PosFrom('',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); LogMessage(' Parse results List Actors:'+ItemList+'||'); curPos:=Pos('',ItemList); //WEB_SPECIFIC While 0'); //WEB_SPECIFIC endPos:=PosFrom('
',ItemList,curPos); //WEB_SPECIFIC ItemValue:=Copy(ItemList,curPos,endPos-curPos); if 1=Pos(' ',ItemValue) then ItemValue:=Copy(ItemValue,2,Length(ItemValue)-1); //WEB_SPECIFIC AddMoviePerson(ItemValue,'','','',ctActors); LogMessage(' Get results Actors:'+ItemValue+'||'); curPos:=PosFrom('',ItemList,endPos); //WEB_SPECIFIC end; end; //Get ~studio~ (several values in a comma separated list) curPos:=Pos('
Productora
',HTML); //WEB_SPECIFIC if 0Productora'); //WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); //WEB_SPECIFIC endPos:=PosFrom('
',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); ItemList:=StringReplace(ItemList,';',',',True,True,False); //WEB_SPECIFIC. For Conuntry coproductions. ItemList:=StringReplace(ItemList,' /',',',True,True,False); //WEB_SPECIFIC AddFieldValueXML('studio',ItemList); LogMessage(' Get results studio:'+ItemList+'||'); end; //Get ~genre~ + ~category (two fields with several values in a comma separated list) curPos:=Pos('
Género
',HTML)+Length('
Género
'); //WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); //WEB_SPECIFIC endPos:=PosFrom('
',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); if 0=Pos('|',ItemList) then begin //WEB_SPECIFIC //Get ~genre~ with not ~category~ in Web "Género". LogMessage(' Parse results List genre:'+ItemList+'||'); curPos:=Pos('">',ItemList)+Length('">'); //WEB_SPECIFIC endPos:=PosFrom('',ItemList,curPos); //WEB_SPECIFIC ItemValue:=Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('">',ItemList,endPos); //WEB_SPECIFIC While 0'); //WEB_SPECIFIC endPos:=PosFrom('',ItemList,curPos); //WEB_SPECIFIC ItemValue:=ItemValue+','+Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('">',ItemList,endPos); //WEB_SPECIFIC LogMessage(' Parse results Genre:'+ItemValue+'||'); end; AddFieldValueXML('genre',ItemValue); LogMessage(' Get results Genre:'+ItemValue+'||'); end else begin //Get ~genre~ with ~category~ in Web "Género". ItemList:=Copy(ItemList,1,Pos('|',ItemList)-1) LogMessage(' Parse results List genre:'+ItemList+'||'); curPos:=Pos('&attr=rat_count&nodoc">',ItemList)+Length('&attr=rat_count&nodoc">'); //WEB_SPECIFIC endPos:=PosFrom('',ItemList,curPos); //WEB_SPECIFIC ItemValue:=Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('&attr=rat_count&nodoc">',ItemList,endPos); //WEB_SPECIFIC While 0'); //WEB_SPECIFIC endPos:=PosFrom('',ItemList,curPos); //WEB_SPECIFIC ItemValue:=ItemValue+','+Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('">',ItemList,endPos); //WEB_SPECIFIC LogMessage(' Parse results Genre:'+ItemValue+'||'); end; AddFieldValueXML('genre',ItemValue); LogMessage(' Get results Genre:'+ItemValue+'||'); //Get ~category~ with ~genre~ in Web "Género". curPos:=Pos('
Género
',HTML)+Length('
Género
'); //WEB_SPECIFIC curPos:=PosFrom('|',HTML,curPos)+Length('|'); //WEB_SPECIFIC endPos:=PosFrom('',HTML,curPos); //WEB_SPECIFIC ItemList:=Copy(HTML,curPos,endPos-curPos); LogMessage(' Parse results List Category:'+ItemList+'||'); curPos:=Pos('">',ItemList)+Length('">'); //WEB_SPECIFIC endPos:=PosFrom('',ItemList,curPos); //WEB_SPECIFIC ItemValue:=Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('">',ItemList,endPos); //WEB_SPECIFIC While 0'); //WEB_SPECIFIC endPos:=PosFrom('',ItemList,curPos); //WEB_SPECIFIC ItemValue:=ItemValue+','+Copy(ItemList,curPos,endPos-curPos); curPos:=PosFrom('">',ItemList,endPos); //WEB_SPECIFIC LogMessage(' Parse results Category:'+ItemValue+'||'); end; AddFieldValueXML('category',ItemValue); LogMessage(' Get results Category:'+ItemValue+'||'); end; //Get ~description~ curPos:=Pos('
Sinopsis
',HTML)+Length('
Sinopsis
'); //WEB_SPECIFIC curPos:=PosFrom('
',HTML,curPos)+Length('
'); //WEB_SPECIFIC endPos:=PosFrom('
',HTML,curPos); //WEB_SPECIFIC ItemValue:=Copy(HTML,curPos,endPos-curPos); ItemValue:=StringReplace(ItemValue,'(FILMAFFINITY)','',True,True,False); //WEB_SPECIFIC ItemValue:=RemoveTags(ItemValue,False); AddFieldValueXML('description',ItemValue); LogMessage(' Get result description:'+ItemValue+'||'); //Date ~Updated~ (choose simple or verbose version) //AddCustomFieldValueByName('Updated',DateToStr(CurrentDateTime)); // Simple //AddCustomFieldValueByName('Updated',DateToStr(CurrentDateTime)+' at '+TimeToStr(CurrentDateTime)); // Verbose //AddCustomFieldValueByName('Updated',DateToStr(CurrentDateTime)+' at '+TimeToStr(CurrentDateTime)+' • '+SCRIPT_NAME+' '+SCRIPT_VERSION); // Annoying Result:=prFinished; exit; end; Result:=prError; exit; end; //------------------------------------------------------------------------------