home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / borland / ib / setups / intrabld / data.z / CRAWLER.JFM < prev    next >
Text File  |  1996-12-11  |  23KB  |  679 lines

  1. //#define DEBUG
  2. /****************************************************************************\
  3. *                                                                            *
  4. * Crawler.jfm  --  Given a URL to start with, this application descends the  *
  5. *                  local web tree indexing all connected pages. It then      *
  6. *                  generates a report that, when viewed through a browser,   *
  7. *                  contains a hyperlink to each page.                        *
  8. *                                                                            *
  9. * Crawler.jfm is part of the web utilities solution application. It is meant *
  10. * to be used by systems administrators who would like to index their site.   *
  11. * Used in conjunction with the intrabot it is possible to detect which       *
  12. * machines are running an http server(using intrabot), and then what pages   *
  13. * are on those servers (using crawler).                                      *
  14. *                                                                            *
  15. * The netsite box on the crawlers main page is linked to the hosts table     *
  16. * created by the intrabot. This makes it easy for you to descend the web     *
  17. * tree of the hosts detected by the intrabot. You may also enter a valid url *
  18. * for any site (eg. http://www.elvisIsKing.com/) and begin your descent      *
  19. * there.(Note when used remotely you are forced to choose a value from the   *
  20. * select control. This is a limitation of the current html specifications)   *
  21. * You MUST limit the scope of your search by filling in the                  *
  22. * appropriate range of ip addresses, otherwise this crawler might attempt a  *
  23. * trip around the entire internet. That would take a very long time          *
  24. * (days, weeks, months, years who knows?).                                   *
  25. *                                                                            *
  26. *                                                                            *
  27. * Dependencies:  reqstURL.dll                                                *
  28. *                localurl.qry                                                *
  29. *                urlque.qry                                                  *
  30. *                borlnd21.jpg                                                *
  31. *                websrc11.jpg                                                *
  32. *                                                                            *
  33. *                                                                            *                                                                            *
  34. * Links to:                                                                  *
  35. *                                                                            *
  36. * Updated 11/12/96 by IntraBuilder Samples Group                             *
  37. * $Revision:   1.6  $                                                        *
  38. *                                                                            *
  39. * Copyright (c) 1996, Borland International, Inc. All rights reserved.       *
  40. *                                                                            *
  41. \****************************************************************************/
  42.  
  43.  
  44. //link to external dlls
  45. extern boolean isLocal(char* /*host*/) "reqstURL.dll";
  46. extern boolean setRange(char* /*numeric internet address*/, char* /*numeric internet address*/)"reqstURL.dll";
  47.  
  48. #define mainPage 1
  49. #define successPage 2
  50. #define errorPage 3
  51. var f = new crawlerForm();
  52. f.argv=CRAWLER.arguments; //this loads arguments into the f.argv.Check the length
  53.                           //and values in onServerLoad.
  54. f.open();
  55. return;
  56. // {End Header} Do not remove this comment//
  57. // Generated on 11/12/96
  58. //
  59. var f = new crawlerForm();
  60. f.open();
  61. class crawlerForm extends Form {
  62.    _sys.scripts.load(_sys.env.home() + "APPS\\SHARED\\CONTROLS.CC")
  63.    with (this) {
  64.       onServerSubmit = class::Form_onServerSubmit;
  65.       onServerLoad = class::Form_onServerLoad;
  66.       onServerUnload = class::Form_onServerUnload;
  67.       color = "white";
  68.       height = 14.6667;
  69.       left = 0;
  70.       top = 0;
  71.       width = 78;
  72.       title = "Intranet Crawler";
  73.    }
  74.  
  75.  
  76.    with (this.urlque1 = new Query()){
  77.       left = 42;
  78.       top = 0;
  79.       sql = "@urlQue.QRY";
  80.  
  81.       active = true;
  82.  
  83.       with (rowset) {
  84.  
  85.  
  86.       }
  87.  
  88.    }
  89.  
  90.    with (this.range1 = new Query()){
  91.       left = 48;
  92.       top = 0;
  93.       sql = "@range.qry";
  94.  
  95.       active = true;
  96.  
  97.       with (rowset) {
  98.  
  99.  
  100.       }
  101.  
  102.    }
  103.  
  104.    with (this.localurl1 = new Query()){
  105.       left = 30;
  106.       top = 0;
  107.       sql = "@localURL.QRY";
  108.  
  109.       active = true;
  110.  
  111.       with (rowset) {
  112.  
  113.  
  114.       }
  115.  
  116.    }
  117.  
  118.    with (this.hosts1 = new Query()){
  119.       left = 36;
  120.       top = 0;
  121.       sql = "@hosts.qry";
  122.  
  123.       active = true;
  124.  
  125.       with (rowset) {
  126.  
  127.  
  128.       }
  129.  
  130.    }
  131.  
  132.    with (this.rule1 = new Rule(this)){
  133.       top = 4;
  134.       size = 2;
  135.       right = 76;
  136.       pageno = 0;
  137.  
  138.    }
  139.  
  140.    with (this.rule2 = new Rule(this)){
  141.       top = 11.5;
  142.       size = 2;
  143.       right = 76;
  144.       pageno = 0;
  145.  
  146.    }
  147.  
  148.    with (this.runButton = new Button(this)){
  149.       onServerClick = class::button1_onServerClick;
  150.       top = 10;
  151.       width = 10;
  152.       text = "Start";
  153.  
  154.    }
  155.  
  156.    with (this.lowIPField = new Text(this)){
  157.       left = 40;
  158.       top = 7;
  159.       width = 28;
  160.       value = "";
  161.  
  162.    }
  163.  
  164.    with (this.highIPField = new Text(this)){
  165.       left = 40;
  166.       top = 8;
  167.       width = 28;
  168.       value = "";
  169.  
  170.    }
  171.  
  172.    with (this.HTML3 = new HTML(this)){
  173.       height = 1;
  174.       left = 30;
  175.       top = 7;
  176.       width = 9;
  177.       color = "black";
  178.       alignVertical = 1;
  179.       alignHorizontal = 2;
  180.       text = "From:";
  181.  
  182.    }
  183.  
  184.    with (this.HTML4 = new HTML(this)){
  185.       height = 1;
  186.       left = 30;
  187.       top = 8;
  188.       width = 9;
  189.       color = "black";
  190.       alignVertical = 1;
  191.       alignHorizontal = 2;
  192.       text = "To:";
  193.  
  194.    }
  195.  
  196.    with (this.HTML5 = new HTML(this)){
  197.       height = 1;
  198.       top = 5;
  199.       width = 76;
  200.       color = "black";
  201.       text = "Running the crawler might take a long time.  Proceed?";
  202.       pageno = 2;
  203.  
  204.    }
  205.  
  206.    with (this.okButton = new Button(this)){
  207.       onClick = class::okButton_onClick;
  208.       top = 7;
  209.       width = 14;
  210.       text = "  OK  ";
  211.       pageno = 2;
  212.  
  213.    }
  214.  
  215.    with (this.backButtonPage2 = new Button(this)){
  216.       onServerClick = class::backButtonPage2_onServerClick;
  217.       top = 9;
  218.       width = 14;
  219.       text = "Back";
  220.       pageno = 2;
  221.  
  222.    }
  223.  
  224.    with (this.errorHTML = new HTML(this)){
  225.       height = 4;
  226.       top = 5;
  227.       width = 76;
  228.       color = "black";
  229.       text = "This is the error page.<br>";
  230.       pageno = 3;
  231.  
  232.    }
  233.  
  234.    with (this.displayArea = new TextArea(this)){
  235.       visible = false;
  236.       height = 4;
  237.       left = 16;
  238.       top = 7;
  239.       width = 54;
  240.       value = "";
  241.       pageno = 2;
  242.  
  243.    }
  244.  
  245.    with (this.html1 = new HTML(this)){
  246.       height = 1;
  247.       top = 5;
  248.       width = 30;
  249.       color = "black";
  250.       text = "Begin at Netsite (URL or IP)";
  251.  
  252.    }
  253.  
  254.    with (this.image1 = new Image(this)){
  255.       height = 3.4167;
  256.       width = 10.25;
  257.       dataSource = "filename WEBSRC11.JPG";
  258.       alignment = 4;
  259.       pageno = 0;
  260.  
  261.    }
  262.  
  263.    with (this.backButtonPage3 = new Button(this)){
  264.       onServerClick = class::backButtonPage3_onServerClick;
  265.       top = 9;
  266.       width = 14;
  267.       text = "Back";
  268.       pageno = 3;
  269.  
  270.    }
  271.  
  272.    with (this.html2 = new HTML(this)){
  273.       height = 2;
  274.       left = 12;
  275.       width = 64;
  276.       color = "80c0";
  277.       text = "<h1>Intranet Crawler</h1>";
  278.       pageno = 0;
  279.  
  280.    }
  281.  
  282.    with (this.host = new Text(this)){
  283.       left = 30;
  284.       top = 5;
  285.       width = 40;
  286.       value = "";
  287.  
  288.    }
  289.  
  290.    with (this.html3 = new HTML(this)){
  291.       height = 3;
  292.       top = 7;
  293.       width = 30;
  294.       color = "black";
  295.       text = "Enter the IP addresses you would like to search between.  (e.g. 123.123.123.123)";
  296.  
  297.    }
  298.  
  299.    with (this.html4 = new HTML(this)){
  300.       height = 1.2083;
  301.       left = 12;
  302.       top = 2;
  303.       width = 64;
  304.       color = "black";
  305.       text = "<H2>will find web objects on the intranet</H2>";
  306.  
  307.    }
  308.  
  309.    with (this.GeneratedHTML1 = new GeneratedHTML(this)){
  310.       height = 1;
  311.       top = 12;
  312.       width = 76;
  313.       pageno = 0;
  314.  
  315.    }
  316.    this.rowset = this.hosts1.rowset;
  317.  
  318.    function button1_onServerClick()
  319.    {
  320.       var errorString=new String();
  321.       if (form.errorsInFields(errorString)){
  322.          form.errorHTML.text=errorString;
  323.          form.pageno=errorPage;
  324.          return;
  325.       }//endif
  326.        //passed initial tests now determine if Netsite value is within the range specified by the user.
  327.       var checkIP=new IpAddress(form.host.value);
  328.       var machineName=new String();
  329.       if (checkIP.isValid){ //this is an address of the form 255.255.255.255
  330.          form.url=new Url("http://"+checkIP.text+"/") //get the default page for this address
  331.          machineName=checkIP.text;
  332.          if (machineName.indexOf(":") > 0){ // Strip off port number if has one.
  333.             machineName=machineName.substring(0,machineName.indexOf(":"));
  334.          }
  335.       } else {   //now check to see if this is a Url
  336.          var tempUrl=new Url(form.host.value);
  337.          machineName=tempUrl.host; 
  338.          if (tempUrl.isValid==false){
  339.             form.errorHTML.text="Error: Netsite is not a valid IP address or URL.<br>";
  340.             form.pageno=errorPage;
  341.             return;
  342.          }//end if
  343.          form.url=tempUrl;
  344.       }//endif
  345.        //set the local range
  346.       if (!(setRange(form.lowIPField.value,form.highIPField.value))){
  347.          form.errorHTML.text="Error: unable to clear resources necessary to proceed. Try again later.<br>";
  348.          form.pageno=errorPage;
  349.          return;
  350.       }//end if
  351.       if (isLocal(machineName)==false){ //must be local
  352.          form.errorHTML.text="Error: Starting machine is not within specified range.<br>";
  353.          form.pageno=errorPage;
  354.          return;
  355.       }//end if 
  356.        //passed all the tests show the success page.
  357.       form.pageno=successPage;
  358.    }
  359.  
  360.    function iterateQue() 
  361.    {
  362.       var tag;
  363.       var i=0;
  364.       var foundMatchingRecord;     
  365.       var string2search=new String();
  366.       var count=0;
  367.       var stringBuffer=new String();
  368.       var dataReturned=new String();
  369.       var returnCode=new StringEx();
  370.       var doRetrieve=true;
  371.       var type=new String();
  372.       form.urlque1.rowset.first();
  373.       while(form.urlque1.rowset.endOfSet==false && form.running==true){
  374.          form.urlque1.rowset.first();                        //go to top of que
  375.          var urlToProcess=new Url(form.urlque1.rowset.fields["URL"].value);        //url comes from top of que
  376.                                                             //all urls in que are valid local urls
  377.          form.localurl1.rowset.beginAppend();                 //first save this url to local url table
  378.          form.localurl1.rowset.fields["URL"].value=urlToProcess.text
  379.          form.url=urlToProcess;
  380.          doRetrieve=filterFiles(urlToProcess,type);  //check this Url to see if we can tell what it is by its extension
  381.          if (doRetrieve==false){
  382.             form.displayArea.value="Getting info on " + urlToProcess.text +"\n";    //show the user what's going on      
  383.             var headResponse=new HeadResponse(urlToProcess);
  384.             processHeader(headResponse.headerFile,type, this);
  385.          }else{
  386.             form.displayArea.value="Retrieving " + urlToProcess.text +"\n";    //show the user what's going on      
  387.             infoFromServer=new HttpResponse(urlToProcess);   //get the response
  388.             processFile(infoFromServer, this);                     //process it
  389.          }
  390.          form.localurl1.rowset.save();
  391.          form.popQue();                                 //remove url from top of que
  392.       }//end while                                     //read in next url
  393.                                  //Finis
  394.       return;
  395.    }
  396.  
  397.    function errorsInFields(errorString)
  398.    {
  399.       var errors=false;
  400.       errorString="";
  401.       var ipLow=new IpAddress(form.lowIPField.value);
  402.       var ipHigh=new IpAddress(form.highIPField.value);
  403.       if(ipLow.isValid==false){
  404.          errorString+="Error: Low IP address is not valid.<br>";
  405.          errors=true;
  406.       }
  407.       if(ipHigh.isValid==false){
  408.          errorString+="Error: High IP address is not valid.<br>";
  409.          errors=true;
  410.       }
  411.       machineRange= (ipHigh.toDecimal()-ipLow.toDecimal())+1;
  412.       if (machineRange<0){
  413.          errorString+="Error:Low address must be a smaller number than the high address.<br>"
  414.          errors=true;
  415.       }//endif
  416.       return errors;
  417.    }
  418.  
  419.    function popQue()
  420.    {
  421.       form.urlque1.rowset.first();
  422.       form.urlque1.rowset.delete(); //erase the top of the que
  423.       return;
  424.    }
  425.  
  426.    function shouldAddToQue(url)
  427.    {
  428.       if (form.checkLocal(url)==false){
  429.          return false;
  430.       }
  431.       if (url.protocol!="http"){
  432.          return false;
  433.       }
  434.       form.urlque1.rowset.beginLocate();
  435.       form.urlque1.rowset.fields["URL"].value=url.text;
  436.       form.urlque1.rowset.applyLocate();
  437.       if (!(form.urlque1.rowset.endOfSet) ){ //already in urlque file
  438.          return false;                         //so we don't need to check it again
  439.       }
  440.       return true;
  441.    }
  442.  
  443.    function checkLocal(url)
  444.    {
  445.       if (!url.isValid) { //must be valid url
  446.          return false;
  447.       }
  448.       if (!isLocal(url.host)){ //must be local
  449.          return false;
  450.       }
  451.       form.localurl1.rowset.beginLocate();
  452.       form.localurl1.rowset.fields["URL"].value=url.text;
  453.       try {
  454.          form.localurl1.rowset.applyLocate();
  455.       }
  456.       catch (Exception e) {
  457.    #ifdef DEBUG
  458.          _sys.scriptOut.writeln("ERROR: " + e.message + " (" + e.code + ")");
  459.          _sys.scriptOut.writeln("       " + url.text);
  460.    #endif
  461.          return false;
  462.       }
  463.       if (!form.localurl1.rowset.endOfSet){ //yes already in local file
  464.          return false;  //if it's already in the local file we don't need to process it again
  465.       }
  466.       return true;
  467.    }
  468.  
  469.    function button2_onServerClick()
  470.    {
  471.       form.iterateQue();
  472.    }
  473.  
  474.    function Form_onServerUnload()
  475.    {
  476.       this.running=false; //keep track of when the form is running
  477.       //unload the class definitions
  478.       _sys.scripts.unload("netClass.js");
  479.    }
  480.  
  481.    function Form_onServerLoad()
  482.    {
  483.       //load the class definitions
  484.       //this speeds up calls to functions defined in this .js file
  485.       _sys.scripts.load("netClass.js");//
  486.       loadExternalFunctions();         //must call this immediately after loading net classes.
  487.       this.submit=this.onServerSubmit;
  488.       this.url=new Url("");
  489.       this.running=true;     //keep track of when the form is running
  490.       if (this.argv.length>0) { //this form was launched with arguments
  491.          this.host.value=this.argv[0];
  492.       }
  493.       if (!(this.range1.rowset.endOfSet)) {
  494.          this.lowIPField.value=this.range1.rowset.fields["low IP"].value;
  495.          this.highIPField.value=this.range1.rowset.fields["high IP"].value;
  496.       }
  497.       this.pageno=mainPage;  //turn to front page
  498.    }
  499.  
  500.    function Form_onServerSubmit()
  501.    {
  502.       var i=0;
  503.       //technical detail. empty the tracking tables first.
  504.       this.urlque1.rowset.first();
  505.       while( !(this.urlque1.rowset.endOfSet) ){
  506.          this.popQue();
  507.       }
  508.       this.localurl1.rowset.first();
  509.       while(!(this.localurl1.rowset.endOfSet) ){
  510.          this.localurl1.rowset.first();
  511.          this.localurl1.rowset.delete(); //erase the top of the que
  512.       }
  513.       if (this.urlque1.rowset.count() >0 || this.localurl1.rowset.count()>0){
  514.          this.errorHTML.text="Error: Unable to clear resources necessary to proceed. Try again later.<br>";
  515.          this.pageno=errorPage;
  516.          return;
  517.       }
  518.       this.displayArea.visible=true;  //Show the display area when running in the ide.
  519.                                       //This will do nothing when viewed through the browser
  520.                                       //the display area will still be invisible there which
  521.                                       //is the way we want it.
  522.       this.urlque1.rowset.beginAppend();  //if yes, put it on the que
  523.       this.urlque1.rowset.fields["URL"].value=form.url.text;
  524.       this.urlque1.rowset.save();
  525.       this.iterateQue(); //now iterate the que
  526.       _sys.reports.run("crawler",1,1);
  527.       this.displayArea.visible=false;  //When functions is finished there is no need to
  528.                                        //display progress.
  529.       return;
  530.    }
  531.  
  532.    function backButtonPage2_onServerClick()
  533.    {
  534.       form.pageno=mainPage; //back to the opener
  535.    }
  536.  
  537.    function okButtonPage3_onServerClick()
  538.    {
  539.       form.pageno=mainPage;
  540.    }
  541.  
  542.    function backButtonPage3_onServerClick()
  543.    {
  544.       form.pageno=mainPage
  545.    }
  546.  
  547.    function getPath(URL)
  548.    {
  549.       // {Export} This comment causes this function body to be sent to the client
  550.       //This function returns the path of the url minus the filename
  551.       var path=unescape(URL.substring(0,(URL.lastIndexOf("/"))+1));
  552.       return path;
  553.    }
  554.  
  555.    function okButton_onClick()
  556.    {
  557.       setTimeout("showStatus()",20000);
  558.       this.form.submit();
  559.       //document.form[0].submit(); //Use this line with MS IE 3.0 . IE still has trouble with Java Script.
  560.    }
  561.  
  562.    function showStatus()
  563.    {
  564.       // {Export} This comment causes this function body to be sent to the client
  565.       var path=getPath(window.location.href);
  566.    //      window.open(path+"update.jfm","","height=200,width=400");
  567.       window.open("/svr/intrasrv.isv?apps/webutils/update.jfm","","height=200,width=400");
  568.    }
  569.  
  570. }
  571. function processReturnCode(header, form)
  572. {
  573.    //this function checks for the 200 ok response
  574.    //If we get it we return true
  575.    //if we don't we mark the error to the table and return false
  576.    var validResponse=true;
  577.    var returnCode=header.returnCode;
  578.    if (returnCode.indexOf("200")<0) { //didn't receive the "200 ok" response
  579.       validResponse=false;
  580.    }//endif 
  581.    return validResponse;
  582. }
  583. function processFile(infoFromServer, form)
  584. {
  585.    if (processReturnCode(infoFromServer.header, form)){
  586.       form.localurl1.rowset.fields["Size of file"].value=infoFromServer.header.contentLength;
  587.       form.localurl1.rowset.fields["Last modified"].value=infoFromServer.header.lastModified;
  588.       form.localurl1.rowset.fields["Type of file"].value=infoFromServer.header.contentType;
  589.       tag= infoFromServer.html.getReferences();      //collect all the href tags
  590.       for(i=0; i<tag.length; i++){                    //check each href tag
  591.          var tempUrl=new Url(tag[i]);   
  592.          if (form.shouldAddToQue(tempUrl) ){
  593.             form.urlque1.rowset.beginAppend();    //add it.
  594.             form.urlque1.rowset.fields["URL"].value=tempUrl.text;
  595.             form.urlque1.rowset.save();
  596.          }
  597.       }//end for
  598.    }else{
  599.       var returnCode=infoFromServer.header.returnCode;
  600.       form.localurl1.rowset.fields["Type of file"].value=returnCode.substring(4,returnCode.length);
  601.    }
  602. }
  603. function processHeader(header,type, form)
  604. {
  605.    if (processReturnCode(header,type,form)){
  606.       form.localurl1.rowset.fields["Size of file"].value=header.contentLength;
  607.       form.localurl1.rowset.fields["Last modified"].value=header.lastModified;
  608.       form.localurl1.rowset.fields["Type of file"].value=header.contentType;
  609.    }else{
  610.       form.localurl1.rowset.fields["Type of file"].value=type;
  611.       form.localurl1.rowset.fields["Size of file"].value="not available";
  612.       form.localurl1.rowset.fields["Last modified"].value="not available";
  613.    }
  614. }
  615. function filterFiles(url,type)
  616. {
  617.    //don't bother retrieving any files with .gif, or .jpeg extension. Those
  618.    //won't have links to other pages.
  619.    var periodIndex=0;
  620.    var badExtensions=new AssocArray();   //construct an array of extensions we don't want to retreive
  621.    badExtensions["zip"]="compressed file";
  622.    badExtensions["jpeg"]="image/jpg";
  623.    badExtensions["jpg"]="image/jpg";
  624.    badExtensions["tiff"]="image/tiff"
  625.    badExtensions["map"]= "map file";
  626.    badExtensions["gif"]="image/gif";
  627.    badExtensions["exe"]="executable";
  628.    badExtensions["bat"]="batch";
  629.    badExtensions["cmd"]="command file";
  630.    badExtensions["pl"]="pearl script";
  631.    badExtensions["sh"]="bourne script";
  632.    badExtensions["csh"]="c-shell script";
  633.    badExtensions["ksh"]="korne script";
  634.    badExtensions["gzip"]="gunzip file";
  635.    badExtensions["tar"]="tar compressed";
  636.    badExtensions["class"]="java applet";
  637.    badExtensions["pdf"]="adobe portable document";
  638.    badExtensions["rtf"]="rich text";
  639.    badExtensions["tex"]="x-tex";
  640.    badExtensions["dvi"]="x-dvi";
  641.    badExtensions["ras"]="raster";
  642.    badExtensions["xbm"]="x-bitmap";
  643.    badExtensions["xpm"]="x-pixmap";
  644.    badExtensions["xwd"]="x window dump";
  645.    badExtensions["ai"]="post-script";
  646.    badExtensions["eps"]="post-script";
  647.    badExtensions["ps"]="post-script";
  648.    badExtensions["cpio"]="x-cpio";
  649.    badExtensions["sit"]="stuffit";
  650.    badExtensions["hqx"]="bin-hex";
  651.    badExtensions["avi"]="video";
  652.    badExtensions["mpeg"]="video";
  653.    badExtensions["mpg"]="video";
  654.    badExtensions["mpe"]="video";
  655.    badExtensions["mpv"]="video";
  656.    badExtensions["mpegv"]="video";
  657.    badExtensions["vbs"]="video";
  658.    badExtensions["ra"]="Real Audio";
  659.    badExtensions["rm"]="Real Audio";
  660.    badExtensions["wav"]="Wave file";
  661.    badExtensions["Z"]="Compressed file";
  662.                                                                 //To find extension
  663.    if (badExtensions.isKey(url.extension)){           //see if it is marked as a type of file we don't
  664.       type=badExtensions[url.extension];                //want to retrieve
  665.       return false;
  666.    }//endif
  667.    return true;
  668. }//end filterFiles();
  669. function getPath(URL)
  670. {
  671.    // {Export} This comment causes this function body to be sent to the client
  672.    //This function returns the path of the url minus the filename
  673.    var path=unescape(URL.substring(0,(URL.lastIndexOf("/"))+1));
  674.    return path;
  675. }
  676. function setTimeout(x,y)
  677. {
  678. }
  679.