SYNDICATION METHODOLOGY TO DYNAMICALLY PLACE DIGITAL ASSETS ON NON-RELATED WEB SITES

Abstract: Digital assets are syndicated by constructing a web page and inserting into the web page JavaScript associated with a digital asset that is desired to be part of a fully rendered web page. The content of the digital asset is not initially part of the web page. The script, when executed by a browser, requests the content of the digital asset from a remote site (1). The request includes a uniform resource identifier (URI) of the web page and a unique identifier of the selected content. The remote site receives the request and authenticates whether the URI is authorized to receive the selected content (3). If so, the remote site locates the selected content and sends the selected content to the web browser (3). The web browser assembles the initially requested web page using the selected content obtained from the remote site (2).

Description: TITLE OF THE INVENTION SYNDICATION METHODOLOGY TO DYNAMICALLY PLACE DIGITAL ASSETS ON NON-RELATED WEB SITES CROSS-REFERENCE TO RELATED APPLICATIONS This application claims the benefit of U.S. Provisional Application No. 60/223,394 filed August 1, 2000, entitled "SYNDICATION METHODOLOGY TO DYNAMICALLY PLACE DIGITAL ASSETS ON NON-RELATED WEB SITES." COPYRIGHT NOTICE AND AUTHORIZATION Portions ofthe documentation in this patent document contain material that is subject to copyright protection. The copyright owner has no objection to the facsimile reproduction by anyone ofthe patent document or the patent disclosure as it appears in the Patent and Trademark Office file or records, but otherwise reserves all copyright rights whatsoever. BACKGROUND OF THE INVENTION The present invention is directed to the process of Active Data Syndication and its use in web development and content management. More specifically, the present invention establishes the mechanism, the framework, the interfaces and the ancillary methodology to allow multiple content creators to offer for targeted syndication or network distribution and retrieval of digital assets across the web and to have those assets present within the constrains ofthe receiving web site, and to automate that process, where warranted. Conventional web sites consist of a wide variety of articles and information compiled and entered independently by a webmaster. Tools abound to facilitate the production of such web sites, from textual HTML editors to visual page designers like Adobe GoLive. Programs like LinkBOT exist to validate links among pages. However, the conventionality of this form of web site generation becomes merely a shell for the advent ofthe more advanced, dynamic and interactive web site. Site management tools allow for the collaborative efforts of site creation, but are significantly limited in their ability to share information and digital assets across the boundaries of web sites. Syndication or distribution of digital assets across the web heretofore involved the direct replication of those assets to a database server under the control ofthe receiving web site manager, and away from the control ofthe supplier ofthe digital asset. Examples of implementations where content replication is the primary form of asset syndication include those from Vignette, Kinecta, Interwoven, ICE, and ArcadiaOne. Accordingly, there is a need for a system which (1) unifies the way digital assets, in any form, are shared from one site to another, (2) unifies the distribution of those digital assets across multiple platforms, (3) allows the owners of digital asset a management tool for tracking the business relationships surrounding the use ofthe digital assets, (4) establishes mechanisms, interfaces and methodology for the secure flow of information through information distribution networks, (5) facilitates the webmaster to have updated digital content present on the web site, and (6) automates the update of web content. The present invention fulfills these needs. Prior to the present invention, it was not possible for web sites governed by any number of normal content management tools to proactively share information with independent and unrelated web sites. The lightweight and transportable tool ofthe present invention allows for a web site to be programmed to receive digital asset information in a multiplicity of formats, and to display those assets within the style and constraints ofthe receiving web site. The web sites need not be collocated, nor do they need to be created using the same tools. They simply need to render HTML in any web browser, capable of interpreting Java and JavaScript. The power of this tool is such that it can enhance, if not revolutionize, the bi-directional communications infrastructure using the web. These managed information distribution networks do for the Internet what faxes and overnight mail did for corporate correspondence two decades ago. SUMMARY OF THE INVENTION The present invention provides a scheme of obtaining selected content for a web page, wherein the selected content itself is not initially part ofthe web page. The web page includes script, such as JavaScript, associated with the selected content. The scheme operates as follows: 1. A web browser requests a web page that includes script associated with the selected content. The selected content may be only a portion ofthe web page. The selected content may be a digital asset or an executable file. In the preferred embodiment, the web page is constructed using HTML, and the script is embedded therein. 2. The web browser interprets the script and formats a request to obtain the selected content from a remote site. The request includes a uniform resource identifier (URI) ofthe web page and a unique identifier ofthe selected content. The URI may be a URL. 3. A remote site, such as a web server, receives the request and authenticates whether the URI is authorized to receive the selected content. If so, then the remote site locates the selected content and sends the selected content to the web browser. The selected content may be stored in a content repository connected to the web server. If the URI is not authorized to receive the selected content, then the remote site sends a signal to the web browser that the selected content is not available, and the web browser assembles the web page without the selected content. 4. The web browser assembles the initially requested web page using the selected content obtained from the remote site. The assembled web page may include one or more content sets from the syndicator, each having its own script for implementing the steps above. In one preferred embodiment, the script includes a subscriber identifier and a content identifier which are both used to create the unique identifier ofthe selected content. The present invention also provides a scheme for syndicating digital assets. A web page is constructed, and script, such as JavaScript, associated with at least one digital asset that is desired to be part ofthe fully rendered web page is inserted into the web page. The script, when executed by a browser, performs modest authentication regarding the URI and requests the content ofthe digital asset from content repository. The request includes a uniform resource identifier (URI) ofthe web page and a unique identifier ofthe selected content. In one preferred embodiment, the script includes a subscriber identifier and a content identifier, which, together, create the unique identifier ofthe selected content. The selected content may be an executable file. BRIEF DESCRIPTION OF THE DRAWINGS The following detailed description of preferred embodiments ofthe present invention would be better understood when read in conjunction with the appended drawings. For the purpose of illustrating the present invention, the drawings show embodiments ofthe present invention which are presently preferred. However, the present invention is not limited to the precise arrangements and instrumentalities shown. In the drawings: Fig. 1 is a schematic block diagram that provides an overview of one preferred embodiment ofthe asset syndication scheme ofthe present invention; Fig. 2 is a database schema for one preferred embodiment ofthe present invention; Fig. 3 is an authentication schema for one preferred embodiment ofthe present invention; Figs. 4-13B are user interface displays (administrative screen shots) for one preferred embodiment ofthe present invention; Fig. 14 is a database schema for the second preferred embodiment ofthe present invention; Figs. 15A and 15B, taken together, are overall. schemas for the second preferred embodiment ofthe present invention; Fig. 16 is a schematic block diagram ofthe second preferred embodiment ofthe present invention; Figs. 17-19 are JavaScript source code snippets for implementing a web application embodiment ofthe present invention; and Fig. 20 is a database schema for the web application embodiment ofthe present invention. DETAILED DESCRIPTION OF THE INVENTION Certain terminology is used herein for convenience only and is not to be taken as a limitation on the present invention. In the drawings, the same reference letters are employed for designating the same elements throughout the several figures. I. DEFINITIONS Content: Any textual, visual, and audio materials or the combination thereof, including animated images, video clips, executable files, or digital assets targeted for presentation. Content Repository: a database of file structure which contains the syndicatable asset. Syndicated Asset: Any content which is available to an authenticated receiver. Authenticated Receiver: A receiver of content that is authorized to retrieve and present that content. Subscriber: Synonym to Authenticated Receiver. Domain: The name which appears in the URL between the "www" and the end ofthe three letter extension (e.g., .com, .net , .org). Example: www.regiononline.com, the domain is regiononline.com. II. OVERVIEW OF PRESENT INVENTION Referring to Fig. 1, the following steps are performed: 1. A request is made from a web appliance to a URL, which contains a web page that has embedded the syndication code. 2. The web page, while rendering other data present on the page, such as navigation, headers and footers, and other assets not related to the syndicated content, returns JavaScript which tests the appliance for the site URL requested. The JavaScript effectively functions as a dynamic content retrieval agent. 3. This information is then used to authenticate the content presence on the site as valid, and then to retrieve from the syndication database those assets for display, and render those syndicated assets through the appliance. The present invention introduces the notion of web real estate and the apportionment of content sections to a particular web page. A visually unified site is substantially divided into sub-sites, or content sections, that are independently maintained by section managers or through syndicated content offerings. As a direct and targeted information management delivery tool, the present invention is useful to the large corporation, a community site, or any site which enables the sharing of targeted information. Any content or information rich site will find this present invention very helpful. The present invention may be used to complement web pages created in MS Frontpage, or any number of content management tools. The present invention does not perform visual layout, and may be considered a post-design tool. The present invention may be used with any number of programming languages such as Cold Fusion, ASP, C++, Java, Visual Basic or Perl. The present invention may serve as an extension to the web page, or an add-on component to any number of content management tools. The present invention may be used on any site that renders HTML, and is intended to be programming language neutral, through the use of JavaScript, servlets, and Java features. πi. DETAILED DESCRIPTION OF ONE PREFERRED EMBODIMENT In one preferred embodiment ofthe present invention as described herein, the user communicates through a browser with the necessary web site via an electronic network, such as the Internet. However, the scope ofthe invention includes other types of user interfaces and electronic networks that are capable of performing the desired functions. The present invention is described in the context of a commercially available software product called Active Data Syndicator™, available from Active Data Exchange, Inc., Bethlehem, Pennsylvania. A. DETAILED EXPLANATION OF FIGURES AND APPENDICES Fig. 2 is a self-explanatory database schema for one preferred embodiment ofthe present invention, and Fig. 3 is a self-explanatory authentication schema for one preferred embodiment ofthe present invention. Fig. 4 is an administrative entry screen for beginning the process. Fig. 5 is a user interface display that allows for the selection from an existing syndication or the creation of a new syndication. Referring to Fig. 6, if the a<iministrator chooses the "go get it" button from the Fig. 5 display, then a listing ofthe syndication offers are presented. The "clickable" first field allows for the modification of that offering. Figs. 7 and 8 are user interface displays a for a "New Setup." The administrator completes the fields shown in these displays. Fig. 9 is a user interface display that allows for the viewing ofthe necessary syndication code for placement into the HTML ofthe subscriber/receiver web site. Fig. 10A shows the actual code for placement on the subscriber/receiver HTML page for the fictitious client Attorney at Law. This code allows for the one time insertion ofthe code for presentation of information, news, events, or other digital assets on an ongoing basis. Fig. 10B shows the same code, modified to present the latest asset, as well as the creation of several hypertext links for viewable archives of older digital assets. In this case, there is the ability to present for viewing up to 10 viewable archives from the database. Figs. 11 and 12 show additional administrative functions for the deletion of a subscriber. Figs. 13A and 13B show the list of subscribers/receivers for overall administrative purposes. Appendix A is the syndication source code for the embodiment ofthe present invention shown in Figs. 2-13B. Appendix B is the servlet package source code for the embodiment ofthe present invention shown in Figs. 2-13B. B. INHERENT SECURITY All web sites do not use the same syndication code. Subtle differences in the code are "keyed" to the receiving domain. It is through this "key" that the integrity of he business relationship and the placement ofthe digital asset are preserved. The process includes a security module that looks at the browser URL ofthe appliance to determine which URL (domain) it is calling. If the domain does not match an existing client URL (coupled with the content authorized for use), a message is returned to the appliance, which states that the content is unavailable. C. WEB SITE SETUP FOR RECEIVING SYNDICATION OFFERINGS To set up a web site page for syndication, a few parameters must be understood and defined: 1. The receiving URL, as authentication or validation ofthe receiver/subscriber is performed to the domain level. 2. The asset section to be syndicated. This refers to a content section in a content management system. One instant example would be to syndicate "What's News" from a company or organization. This section ofthe site is a hypothetical region where all information regarding press releases and latest organizational information is to be found. In this installation, the site only needs to be set up with the HTML snippet one time. Content changes occur dynamically. 3. The number of displayed archives the receiver would like to be able to view. This is a title listing of previously syndicated content for this section. 4. The database location ofthe digital asset. 5. The organizational name (for administrative purposes). 6. The start and end time for the syndication. This is important if the syndicated asset is time dependant or whether or not the subscription to the syndicated digital asset is on a monthly or other time dependent basis. Through these parameters, metrics can be derived which display, from the syndication-offered standpoint, several management reports useful in understanding the offerings and their use. Metrics include: 1. Number of times a digital asset is accessed by a subscriber (useful in fee per use models as well as for tracking relative worth ofthe asset). 2. Places where the digital asset can be viewed/authorized domains. 3. Listing ofthe offerings available for release through the syndication model. 4. Through an oblique methodology, a measure ofthe physical overhead of the device housing that content. D. DATABASE INTERRELATIONSHIPS As discussed above, the present invention is platform independent and program neutral. It functions equally as well on operating systems written in Microsoft, as it does from that of Red Hat Linux. Furthermore, the database from which it pulls its content may either be MS SQL, Informix, Sybase or Oracle, as it uses command phrases which are non-vendor specific (ANSI SQL). The hardware, however, must be of sufficient strength to power databases that conceivably will receive hundreds of thousands of requests per second. Fig. 2, described above, illustrates one preferred database schema for the present invention. E. ARCHITECTUAL OVERVIEW The implementation of this business process and its underlying software is hardware independent, providing that the following applications/services are available: An application server running a servlet engine such as Allaire's JRUN or TomCat, and a web server such as Internet Information Server (ES) from Microsoft or an Apache web server should the operating system ofthe server be RedHat Linux or Unix. The database server should have a strong relational database such as MS SQL, Oracle, or Sybase, overtop ofthe appropriate operating system. The location ofthe servers used in the present invention can be anywhere within the infrastructure ofthe existing client network. One suitable scheme is to locate the servers behind a redundant firewall. The invention environment provides for all system hardware requisite to the invention work. It includes an application/web server that controls the look of web pages, serves content for the web pages, and provides the environment for the administration of those tasks. The standard operating system for this invention is Linux. However, a client may choose Windows NT or UNIX as an alternate operating system (OS). Coupled with the OS, a web server needs to be chosen. In the example of Red Hat Linux, one suitable choice would be Apache. However, a Windows NT environment would most likely use IIS. Since the present invention is a Java-based application, a servlet engine needs to be incorporated into the server operation. One suitable configuration to support the invention includes the following elements: Operating System (Application Server) Windows NT 4.0 with Service Pack 6A Red Hat Linux 6.2 Databases (Database Server) Sybase 11.02 [Windows NT, Linux] Oracle 8i Server 8.1.5 [Windows NT, Solaris, Linux] Microsoft SQL Server 6.5 with Service Pack 6A [Windows NT Only] Microsoft SQL Server 7.0 [Windows NT Only] JDBC Drivers Microsoft SQL Server 6.5, 7.0: SPRTNTA JDBC 2.0 Driver version 2000 [Type 4] Oracle 8.0.5.0. Production release JDBC [Windows NT, Solaris, Linux] HTTP Servers (Web Server Types) Operating JRUN 2.3.3 or greater Netscape Enterprise Server 3.0, 3.6 [Windows NT, Solaris, Linux, ATX] Microsoft Internet Information Server Version 4.0 [Windows NT Only] Apache and Stronghold Web Server 2.4.2 [NT, ATX, Solaris, Linux] Java Development Kit (JDK) Recommendation: Sun Compliant JDK minimum version 1.2.2 Example Configurations: 1. Linux Application Server with NT OS running the Database server Application/Web Server: Red Hat Linux version 6.2 with an Apache web server. Database Server: Microsoft NT 4.0 with Service Package 6A and MS SQL version 7 as the database. 2. Linux Application Server with Linux OS running the Database server Application/Web Server: Red Hat Linux version 6.2 with an Apache web server. Database Server: Red Hat Linux version 6.2 with Oracle 8i as the database. 3. NT Application Server with NT OS running the Database server Application/Web Server: Microsoft NT 4.0 with Service Package 6A and IIS version 4 with full options as the Web Server. Database Server: Microsoft NT 4.0 with Service Package 6A and MS SQL version 7 • as the database. The Database Server becomes more critical as database size increases over time. It is feasible for an installation to use a different OS for the application server than that ofthe database server. Different database engines serve data at different rates (some faster than others) and some networks operate with corporate standards which mandate the use of certain configurations, to standardize application environments for ease of maintenance. For those reasons, the publishing database was developed platform independent. It is functionally transparent whether or not it is installed over Oracle, Sybase, MS SQL or Informix. The present invention may be installed as part of a related product from Active Data Exchange, Inc., called Active Data Publisher™/Web Server, or it may be a functionally independent device. The setup ofthe environment ofthe present invention is the same as the Application/Web server environment. F. EXAMPLES OF SYNDICATION USE AND APPLICATION Case One: Large organization with multiple web sites (Public and Private) A large organization has multiple web sites to manage, both public (visible to all) and private (internal and departmental in nature). The sites are repositories for a wide variety of information specific to their department of corporate division. There are, however, many assets which are frequently reproduced and shared among those sites. If a directive from Senior Management needs to be presented on each ofthe sites, conventional content management tools would require the HTML editors to re-post the directive on each and every site. This repetitive process creates organizational inefficiencies. Using the present invention, an HTML snippet is placed on the page in the place where information bulletins will be seen. (See Figs. 10A and 10B which illustrate an HTML snippet.) Every time a new information bulletin is released, the web page is automatically updated, without technology intervention. Furthermore, the bulletin is created in the native environment frequently used by the author or their assistant, and posted once through an intuitive, easy to use interface module which converts the document to HTML, enters the data into the syndication database, and prepares it for view on the site. Case Two: Supply Chain Information Management A manufacturer manages information streams from raw materials suppliers (upstream providers) to distributors (end users). The management objective is to assure that the end user receives the completed goods at a fair price in a timely manner, and that the raw materials suppliers notify the manufacturer of delays in shipments, which, in turn, affect product availability. If one believes that the main differentiation between suppliers of similar materials is their ability to enhance communications with clients and vendors, and that issue singularly is what is going to set apart one from another, then the implementation ofthe tools provided by the present invention is the linchpin in corporate success. In this example, it is helpful from a supply management role to understand the needs ofthe client and the ability for the vendor to supply product to create the materials for the client. Subscribing to the notion of apportioned web real estate, and having particular areas designated for information relevant to those in the supply chain, a new communications modality is created called a Digital Information Network that is linking the supplier and the end user in such a fashion as to be able to enhance the decision process, increase productivity, and enhance the digital economy. IV. DETAILED DESCRIPTION OF A SECOND PREFERRED EMBODIMENT The second preferred embodiment may be used with Active Data Syndicator v.3. A. DETAILED EXPLANATION OF FIGURES AND APPENDIX Fig. 14 is a self-explanatory database schema for the second preferred embodiment. Fig. 14 shows only the portion ofthe database schema that relates to the present invention. Figs. 15A and 15B, taken together, are self-explanatory overall schema for the second preferred embodiment. Fig. 16 is a schematic block diagram ofthe second preferred embodiment. Appendix C is the combined syndication and servlet package source code for the embodiment ofthe present invention shown in Figs. 14-16. B. IMPLEMENTATION OF SECOND EMBODIMENT Fig. 16 shows an overview ofthe second preferred embodiment. The basic elements include web pages located at a plurality of different URLs, a viewing browser, an application web server that hosts the syndication product, and a content repository. Each of these elements may be interconnected by any suitable communication medium, such as the Internet. The process operates as follows: 1. A user at the viewing browser requests a web page from a particular web site. The requested web page contains HTML elements, as well as at least one snippet of JavaScript associated with the syndicated digital asset. Alternatively, the requested web page does not have to reside on a web site. The requested web page may also be a simple HTML file stored on the hard drive of a user's local computer in cases where an authenticating URL is not required. 2. The snippet of JavaScript is received by the browser. 3. When the JavaScript is received, it is not immediately used by the browser on the part ofthe web page on wliich it resides. Instead, the "src" attribute ofthe JavaScript tag is used to make a call to a Java servlet. More specifically, the JavaScript forms an HTTP (or HTTPS) request that includes a URI (e.g., a URL) ofthe requested web page as obtained from the browser, and a unique identifier contained within the JavaScript. In one preferred embodiment, the unique identifier is a combination of a subscriber identifier (sub ID) and a content identifier (content ID). In effect, the HTTP request is saying that URI [xyz] is requesting content [123], and is asking if it is okay to deliver it. The HTTP request is sent to an application web server that is designated by an address located within the JavaScript. 4. At the application web server, the syndication product receives the URI and the unique identifier, 5. The syndication product then looks in an authentication table to determine if there is a matching URI and unique identifier. If so, then the unique identifier is parsed to obtain the sub ID and content ID. The sub ID is used to check the current account status ofthe subscriber, and the content ID is used to locate the content in the content repository. 6. Assuming that a match is found in the authentication table, the subscriber ED is properly authorized, and the content is located in the content repository, then the content is retrieved from the content repository and sent by the syndication product to the browser for insertion at the appropriate location during the rendering ofthe web page. To facilitate this process, the syndication product contains content filtering and parsing methods (called "parseContent" and "swapStrings" in the example source code) which are used to prepare the content so that it can be rendered appropriately in the web page via a JavaScript "document.write" statement. If no match is found in the authentication table, and/or if the subscriber ID is not properly authorized, then a message is returned indicating that requested content cannot be received. Alternatively, no message is returned and the user merely does not receive the requested content. If the content is a text article, the web page may have a blank portion where the requested content would have appeared. If the content is multimedia-oriented, such as an audio file, then such content is not experienced. 7. The syndication content manager updates its records to reflect the activity. The manager may track content retrievals and charge subscriber accounts (if any exist) for such content retrievals. The content manager may remove an entry from the authentication table based upon expiration dates, number of retrievals, or any other suitable factor. The process described above preferably occurs seamlessly in near real-time. Thus, the user is not aware that content (which is typically only a portion ofthe web page, but could be the entire content ofthe web page) is being requested and delivered from a remote content repository during the rendering ofthe web page. The term "web application" as used herein refers to dynamic HTML web site content which varies depending upon user input, includes one or more interactive forms, involves the use of a web server programming/scripting language (e.g., Java, Perl, Cold Fusion, Active Server Pages, etc.), and may also make use of a backend database server for data storage. Some common examples of web applications include guestbooks, forums and shopping carts. Web applications typically execute on the same server as the hosting web server. This arrangement can place significant strain on the web server, especially when a large number of users are simultaneously requesting service and/or many web sites and applications are running concurrently on the same server. (This situation often occurs with ISP's.) The present invention leverages the JavaScript capabilities ofthe user's browser to execute the web application at a remote server independent ofthe subscriber's hosting web server, thereby reducing the potential load on the subscriber's web server and greatly simplifying the process by which a web application can be incorporated into a subscribing web site. That is, simply include the JavaScript snippet ofthe application using the present invention's syndication methodology in the HTML on the subscriber's web site. No further programming is then needed on the subscriber's web server. The user's browser effectively invokes the remote web application that runs and makes the subscriber's web page dynamic. The present invention may be used for flat (static) sites and flat sites having one or more dynamic sections, as well as for fully dynamic sites. The present invention is further advantageous because the traffic for creating the web pages uses port 80 (for http traffic) and port 443 (for https traffic), and thereby can pass through most server firewalls. C. WEB APPLICATION EXAMPLE Active Data Randomizer, available from Active Data Exchange, Inc., Bethlehem, Pennsylvania, is an example of a simple web application which incorporates the syndication methodology ofthe present invention. Randomizer produces two syndicated assets from two different JavaScript snippets. Fig. 17 shows the first JavaScript snippet which renders in the browser as an administrator area (see Fig. 18) for the subscribing web site administrator to use in the configuration and entry of groups of HTML blurbs. Fig. 19 shows the second JavaScript snippet which is generated from the administrative area and renders in the browser as a randomly selected HTML blurb from a group of HTML blurbs specified during the generation ofthe snippet. Appendix D is a User Guide for this embodiment, and Appendix E shows sample source code for this embodiment. The present invention may be implemented with any combination of hardware and software. If implemented as a computer-implemented apparatus, the present invention is implemented using means for performing all ofthe steps and functions described above. The present invention can be included in an article of manufacture (e.g., one or more computer program products) having, for instance, computer useable media. The media has embodied therein, for instance, computer readable program code means for providing and facilitating the mechanisms ofthe present invention. The article of manufacture can be included as part of a computer system or sold separately. It will be appreciated by those skilled in the art that changes could be made to the embodiments described above without departing from the broad inventive concept thereof. It is understood, therefore, that this invention is not limited to the particular embodiments disclosed, but it is intended to cover modifications within the spirit and scope ofthe present invention as defined by the appended claims. What is claimed is: Appendix A Syndication Source Code import j ava . io . * ; import javax. servlet . * ; import javax. servlet . http . * ; import Java. util . Vector; //most methods of Vector are synchronized import j ava . net . * ; /** * Servlet to retrieve content from Publisher server * Takes 7-9 parameters : * * db, contentServer, linkBase, SectionlD, ArticlelD, PartlD, mode, unit, number * * ©author Technology * βauthor ActivedataX. com * Last changed 11/9/99 */ public class ContentNOWjs extends HttpServlet implements Constants { private static int itemsToKeep = 100 , minutesToLive = 10 ; // iπit i may set the values later private static long lastModif ied; private static Vector contents = new Vector ( ) ; private Sentinel sentinel = new Sentinel (itemsToKeep, minutesToLive) ; private static final ReadURL serverURL = new ReadURL O ; public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String contentID, detail; boolean ne Content = false; Content cont; //needed for lookup Params params = new Para s(req); //decipher the request String ContentID = params .contentServer //req.getParameter ( "Server") + "?db=" + params.db + "&SectionID=" + params. SectionlD + "&ArticleID=" + params.ArticlelD + "&PartID=" + params . PartlD + "&ln=" + params. linkBase + "&mode=" + params . ode; if (params.unit != null) {ContentID = ContentID + n {_unit=" + params. nit + "&number=" + params .number; } if (params. te plateURL == null) { params.templateURL = "http://www.lehighvalleynow.com/rol/template4.asp" ,- } A-l ContentID = ContentID + "&tpl=" + params. templateURL; // parameter tpl will be ignored by serverURL.getContent, used for internal ID only cont = lookup (ContentID) ; if (cont != null) detail = cont .detail,• else t try { System. out .println (ContentID) ; detail = serverURL.getContent (ContentID) ; detail = convertTojs (detail, params) ; newContent = true; ) catch (Exception ex) (detail = ex. toString () ; } } //PrintWriter out = resp.get riter ( ) ; // ServletOutputStrea bombs with \u0018: CharConversionException //out.prin (detail) ; //System.out.println (detail) ; OutputStream out = resp.getOutputStreamO ; out. rite (detail .getBytes {) ) ; System. out.println (detail) ; out. flus ( ) ; out .close () ; if (newContent) { lastModified = System. currentTimeMillis () ; cont = new Content (ContentID, detail, lastModified) ; contents. addElemen (cont) ; ) } public long getLastModified(HttpServletRequest req) { return lastModified/1000*1000; } private String convertTojs (String htmlText, Params params) { htmlText = htmlText .replace ( ' \r ' , ' '); htmlText = htmlText.replace (' \n' , ' ' ) ; htmlText = swapStrings (htmlText, "\\", backslash); htmlText = swapStrings (htmlText, "V", apostrophe); htmlText = swapStrings (htmlText, "\"", doubleQuote) ; if (params.ArticlelD. equals ("0") ) { htmlText = JavaScript .openArtxcle ( ) + makeJavascriptHrefs (htmlText, params) ,- } return "document .write (\ n " + htmlText + "\");"; } // pre-pend JavaScript .expandHeader ( ) here for use by all header A-2 items . // //+ the above line is skipped mysteriously // specific full article, just print // parse out href=, get ArticlelD, replace with javascript : expandHeader (ArticlelD) private String makeJavascriptHrefs (String htmlText, Params params) { //find "<a", find "href=", find "ArticleID=" , find ">' //replace href= with javascript : expandHeader (ArticlelD) int indexBeginA, indexHref, indexArticlelD, ArticlelDEndsAt, indexEndA, indexClosingA; String ArticlelD = null; String htmlTextLowercase = htmlText . toLowerCase ( ) ; StringBuffer newHtml = new StringBuffer ( ) ; int indexStart = 0; indexBeginA = htmlTextLowercase. indexOft "<a ", indexStart); indexHref = htmlTextLowercase. indexOf { "href=" , indexBeginA + 2); indexArticlelD = htmlTextLowercase. indexOf ( "articleid=" , indexHref + 5) + 10; indexEndA = htmlTextLowercase . indexOf (">" , indexArticlelD); indexClosingA = htmlTextLowercase. indexOf ( "</a>" , indexEndA) + 4; while (indexBeginA >= 0 && indexBeginA < indexHref && indexHref < indexArticlelD &&• indexArticlelD < indexEndA && indexEndA < indexClosingA) { ArticlelDEndsAt = htmlTextLowercase . indexOf ("&" , indexArticlelD) ; //ArticlelD = 'a' + htmlTextLowercase. substring (indexArticlelD, ArticlelDEndsAt); ArticlelD = htmlTextLowercase. substring (indexArticlelD, ArticlelDEndsAt) ; newHtml . append (htmlText . substring (indexStart, indexHre ) ) . append ( "href=" ) ; newHtml .append( "\\\" avascript :openArticle(\\\ ' " + params . templateURL + "?ΞectionID=" + params. SectionlD + "&ArticleID=" + ArticlelD + "&:PartID=2&db=" + params. db + "\\\ ' ) ; \\\" " ) ; //newHtml .append ("\\\"javascript : expandHeader ( " + ArticlelD + ");\\\""); newHtml. appen (htmlText. substring (indexEndA, indexClosingA)); // done with one anchor. //newHtml . appen (JavaScript . ppendArticleMain (params .requestURL, params. db, params. SectionlD, ArticlelD) ); //new loop starts over indexStart = indexClosingA; indexBeginA = htmlTextLowercase. indexOf ( "<a ", indexStart) ; indexHref = htmlTextLowercase.indexOf ( "href=" , indexBeginA); indexArticlelD = htmlTextLowercase. indexOf ( "articleid=" , indexHref + 5) + 10; indexEndA = htmlTextLowercase. indexOf ( ">" , indexArticlelD) ; indexClosingA = htmlTextLowercase. indexOf ( "</a>", indexEndA) .+ A-3 ; //else use old value to get the tail. ) //newHtml. appen (htmlText. substring (indexClosingA) ) ; return newHtml . toString ( ) ; Content looku (String contentID) { Content con ; int index = -1; for (int i=0; i<contents. size() ; ++i) { cont = (Content) contents. elementAt (i) ; if (contentID. equals (cont .contentID) ) { return (Content) contents .elementAt (i) ; ) ) return null; } public void destroy() { sentinel . uit = true; contents = null; ) class Content { String contentID, detail; long timestamp; Content (String contentID, String detail, long timestamp) { this. contentID = contentID; this. detail = detail; this. timestamp = timestamp/ 60000; //converts millis to min } } /* * * Monitors the content collection, trims and freshes . */ private class Sentinel extends Thread { int itemsToKee ; int minutesToLive; boolean quit = false; Sentinel (int itemsToKeep, int minutesToLive) { this. itemsToKeep = itemsToKeep; this .minutesToLive = minutesToLive; A-4 setPriority(Thread.MIN_PRIORITY) ; star ( ) ; /** * The only and single thread */ public void run() { int itemsToRemove; while ( iquit ) // this keeps cleanup alive until servlet is destroyed. { freshen ( ) ; if (contents. size ( ) > itemsToKeep) trim( ) ; //System. gc() ; try{ Thread. sleep (5000) ; )catch (InterruptedException ex) {} } } private void trim() { int itemsToRemove = contents .size () - itemsToKee ; int trimmed = 0; for (int i=0; i<itemsToRemove; ++i) { contents .removeElementAt (i) ; Thread.yiel ( ) ; trimmed++; } if (triiraned > 10) contents. trimToSizeO ; } private void freshen () { long currentTime = System.currentTi eMillis {) /60000; Content cont; for (int i=0; i<contents.size () ; ++i) { cont = (Content) contents.elementAt (i) ; if (cont. timestamp + minutesToLive < currentTime) { contents.removeElementAt (i) ; Thread.yield() ; } } ) A-5 public String getServletlnfo () { return "Retrieves content from PublishNOW server" ; } public void init (ServletConfig config) throws ServletException { super. init (config); if ( getlnitParameter ( "itemsToKeep") != null ) { try{ this. itemsToKeep = Integer.parselnt (getlnitParameter ( "itemsToKeep" ) ) ; ) catch (NumberFormatException e) { this.itemsToKeep = 100; ) } else this . itemsToKeep = 100; if ( getlnitParameter ( "minutesToLive" ) != null ) { try{ this. inutesToLive = Integer .parselnt (getlnitParameter ( "minutesToLive") ) ; ) catch (NumberFormatException e) { this.minutesToLive = 15; ) ) else this. inutesToLive = 15; } String swapStrings (String Textln, String OldString, String NewString) { int OldStringStartAt; int OldStringLength = OldString. lengt ( ) ; int NewStringLength = NewString. length!) ; String TempText = Textln; OldStringStartAt = indexOfIgnoreCase (TempText, OldString, 0) ; while (OldStringStartAt != -1) { TempText = TempText . substring ( 0, OldStringStartAt) + NewString + TempText. substring (OldStringStartAt + OldStringLength) ; OldStringStartAt = indexO IgnoreCase (TempText, OldString, OldStringStartAt + NewStringLength) ; } return TempText,- } int indexOfIgnoreCase (String TempText, String substring, int StartAt) A-6 { return TempText . toLowerCase ( ) . indexOf ( substring. toLowerCase ( ) , StartAt) ; } } class ReadURL { public String getContent (String SourceURL) throws Exception { URL page; BufferedReader in; int len; page = new URL (SourceURL) ; in = new BufferedReader(new InputStreamReader(page.openStreamO )) ; long time = System. currentTimeMillis () ; CharArrayWriter chbuffer= new CharArrayWriter() ; chart] cbuf = new char[1024]; while ((len = in . read (cbu , 0, 1024)) != -1) { chbuffer.write (cbuf , 0, len); } in.close( ) ; time = (int) (System.currentTimeMillis () - time); return chbuffer.toString () + "<etime " + time + "ms/>"; } } class JavaScript implements Constants{ static String expandHeader() { return "<script language=\\\"JavaScript\\\">function expandHeader (ArticlelD) " + " {ArticlelD. style. isplay = (ArticlelD. style. isplay == \\\"none\\\")? \\\ n \\\" : \\\"none\\\" )<\\/script> » ; } static String openArticle { return "<script language=\\\"JavaScript\\\">function openArticle(url) " + " {var kk = window. open (url, \\\ 'RegiononlineXW ' , \\\ 'resizable=yes,menubar=yes, scrollbars=yes,width= 640,height=400\W) ; )<\\/script> » ; } static String appendArticleMain (String contentServer, String db, String SectionlD, String ArticlelD) { return "<div ID=\\\"" + ArticlelD + "\\\" style=\\\"display:none\\\">" + "<script language=\\\"JavaScript\\\" " + "src=\\\"° + contentServer //req.getParameter ( "Server") + "?db=" + db A-7 + "&SectionID=" +. SectionlD + "&ArticleID=" + ArticlelD. substring (1) + "&PartID=2\\\"x\\/script>" .+ endDiv; ) interface Constants{ static final String apostrophe = "\\V" //used in document .write () static final String doubleQuote = "\\\"' //used in document.write () static final String backslash = "\\\\"; //used in document .write 0 static final String beginScript = "<script language=\"javascript\ ">" ,- static final String endScript = "<\\/script>" ,- //static final String beginDiv = "<div static final String endDiv ,="</div>"; static final String newline = "\r\n"; A-8 Appendix B package com.rnci. roducts.PublishNow; Import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; import ava.sql.*; import java.net.*; import com. rnci.products.DataModules.eP_.«aa,- import com. rnci .products .DataModules.HttpServletDb; pizhlic class jSyndicate extends HttpServletDb { private static String controlDb = " olcontrol"; private static String controlServer = "stoudt"; private static String defaultURL = "htt :// 3 syndicate.rnci . com/servlet/com.rnci.products.PublishNow.jContent"; private static String defaultServer = "stoudt"; private static String defaultDb = "epublish"; private static String defaultSectionID = "bne s"; private static String defaultDocumentURL = "http://www.lehighvalleynow.com/rol/tejnplate4.asp"; private static int itemsToKeep = 200, minutesToLive = 3; //may be set by init() later private static long last-Modified; private static Vector contents = new Vector (); private Sentinel sentinel = new Sentinel (itemsToKeep, minutesToLive); pblic void ini (ServletCon ig config) throws ServletException { super.init (config) ; if (getlnitParameter ("itemsToKeep") !== null) { try { this.itemsToKeep = Intege . arseln (getlnitParameter ("itemsToKeep") ) ; } catch (NumberFormatException e) { this.itemsToKeep = 100; } } else this. itemsToKeep = 100; if (getInitParameter("minutesToLive") != null) { try < this .minutesToLive = Integer. arselnt (getlnitParameter ("minutesToLive") ) ; } catch (NumberFormatException e) { this .minutesToLive = 5; ) } else this.minutesToLive = S; ) public void destroy() { sentinel,quit = true; contents =* null; ) //Process the HTTP Get request public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String HTMLtext, overRide, SectionlD, server, db, templateURL, refererURL, documentURL, redirectURL, unit, contentID, newWindow; int position, ArticlelD, PartlD, mode, number; boolean newContent = false, overrideDe aults = true; Content cont; B-l refererURL =- req. getHeader ("REFERER") ; // default is to use URL params overRide = req. getPara eter ("overrideDefaults") ; if (overRide != null) { if (overRide. startsWith (" ") ) overrideDefaults = false; } //Document URL documentURL = req.getParameter ("documentURL") ; { , //if (unit.length-0 < 3) unit = "<p>"; position = unit. lastlndexO (","); if (position >= 0) unit = (overrideDefaults)? unit, substring (0, position): unit, substring(position + 1); ) //The number of teaser delimiters to count String numbers = req. getParameter ("number") ; if (numbers = null) numbers = "4"; else { position = numbers. lastlndexO (",") ; if (position >= 0) numbers = (overrideDefaults)? numbers. substring(0, position): numbers, substring (position + 1); } try { number = Integer. arselnt (numbers) ; ) catch (Exception e) { number = 4; } Connection cnn = null; contentID = new indow + "," + server + "," + db + "," + SectionlD + "," + ArticlelD + ", " + mode '+ + unit + "," + number + ", " + templateURL; String validated = valxdateReques (templateURL, documentURL, refererURL, db, SectionlD); if (validated. equals ("R") ) { if (documentURL.indexOf ("?") != -1) { redirectURL = documentURL + "sredxrected=yes"; } else { redirectURL = documentURL + "?redxrected=yes"; ) HTMLtext = " location.href = \"" + redirectURL + "\";"; } else if (validated. equals { "E") ) { HTMLtext = " document.write('<BRXB>A network error occurred in connecting to the database. Please try again.</B>' ) ; "; ) else if (validated. equals ("N") ) { HTMLtext = " document. rite{'<BRXB>This web site is not authorized to display the content requeste .</B> * ) ; "; } else { cont = looku (contentID) ; if (cont !=* null) { HTMLtext = cont.detail; } else { newContent = true; if ((SectionlD != null) SS (db != mill) SS (server != null)) { try { cnn = dataConnMan.getConnection(server, db) ; ePress thisOne = new ePress (cnn) ; thisOne. setLink (templateURL) ; thi3θne . setDb (db) ; B-2 if ( (unit != noil) SS (number > 0) ) { //getTeaser HTMLtext = thisOne. getTeasers (SectionlD, ArticlelD, PartlD, mode, nit, umber) i ) else { . //getContent HTMLtext = thisOne. getContent (SectionID,ArticleID, PartlD, ode) ; ) HTMLtext = swapStrings (HTMLtext, "Sdb=", "&server=" + server + "StemplateURL=" + URLEncoder. encode (templateURL) + "&db=") ; if (newWindow. oLowerCase ( ) . startsWith ("y") ) { // add the "target=_blank" to article Hrefs HTMLtext = makeArticleHref s (HTMLtext) ; } dataConnMan. freeConnection(server, db, cnn) ; } catch (Exception e) { HTMLtext = "<! Error connecting to database: " + e.toStringl) + "—" + server + " >"; } ) els { HTMLtext = "<! The SectionlD, server, and db parameters are required, >"; } HTMLtext = convertToj s (HTMLtext, documentURL, refererURL) ; } if (documentURL == null) documentURL = defaultDocumentURL; //Should part 1 links bring up a new browser window? newWindow = req. getParameter ("newWindow") ; if (newWindow = null) newWindow = "no"; position = newWindow. lastlndexOf (", ") ; if (position >= 0) newWindow = (overrideDefaults) ? newWindow. substring(0, position.) : newWindow. substring (position + 1) ; //The Requested SectionlD SectionlD = req. getParameter ("SectionlD" ) ; if (SectionlD == null) SectionlD = defaultSectionlD; position = SectionlD. laβtlndexO (", ") ; if (position >= 0) SectionlD = (overrideDefaults) ? SectionlD. substrin (0, position) : SectionlD. substring (position + 1) ; //The Requested Artxclel (0 for most recent article) String ArticlelDs = req. getParameter ( "ArticlelD" ) ; if (ArticlelDs == null) ArticlelDs = "Opposition = ArticlelDs . lastlndexOf {", ") ; if (position >= 0) { if (overrideDefaults) ArticlelDs = ArticlelDs. substrings, position) ; else ArticlelDs = ArticlelDs . substring (position + 1) ; ) try { ArticlelD = Integer. parselnt (ArticlelDs) ; } catch (Exception e) { ArticlelD = 0; } //The Requested Part (1 for title, 2 for main content) String PartlDs = req. getParamete ("PartlD") ; if (PartlDs = null) PartlDs = "Imposition = PartlDs. lastlndexOf (", " ) ; if (position >- 0) { if (overrideDefaults) PartlDs = PartlDs. substring (0, position) ; else PartlDs = PartlDs . substring (position + 1) ; ) try { PartlD = Integer. pa selnt (PartlDs) ; } catch (Exception e) { PartlD = Z; J //Database Server server = req. getParameter ("server") ; if (server == null) server = defaultServer; position = server. lastlndexOf (", ") ; if (position >= 0) server = (overrideDefaults) ? serve . substring ( 0 , position) : server. substring (position + 1) ; B-3 //PublishNow Database db = req. getParameter (" db" ) ; if (db = null) db = defaultDb; position = db. lastlndexOf (", ") ; if (position >= 0) db = (overrideDefaults) ? db . substring < 0 , position) : db. substring (position + 1) ; //Forward Link Template URL templateURL = req. getParameter ("templateURL" ) ; if (templateURL == null) templateURL = documentURL; //if no templateURL is supplied, set templateURL equal to the current document position = templateURL. lastlndexO (", ") ; if (position >= 0) templateURL = (overrideDefaults) ? templateURL. substring(0, position) : templateURL. substring (position + 1) ; //try { templateURL = URLDecoder . decode (templateURL) ; } //catch (Exception e) { } if (templateURL. indexOf ("SectionID=") != -1) { //if article detail page is same as part 1 links page templateURL = templateURL. substring (0, documentURL. indexOf ("SectionID=") - 1) ; } //The iCount Parameter in ePress.Java String modes = req. etParamete ("mode"); if (modes == null) modes = "Imposition = modes. lastlndexOf (",") ; if (position >= 0) { if (overrideDefaults) mode3 = modes. substring(0, position) ; else modes = modes . substring (position + 1); } try { mode = Intege .parseln (modes) ; } catch (Exception e) { mode = 1; ) //The delimiting string for Teaser requests unit = req. getParameter ("unxt") ,- if (unxt == null) U ) PrintWrxter out = r es . getWriter ( ) ; res . setContentType ( "text/html" ) ; //res . setHeader ("Cache-Control", "no cache") ; //only seems to effect images ou . println (HTMLtext ) ; if (newContent) { lastModified = System. currentTimeMillis () ; cont = new Content (contentID, HTMLtext, lastModified) ; contents . addElement (cont) ; } 5 private String valxdateRequest (String templateURL, String documentURL, String refererURL, String db String SectionlD) { ' //returns "Y", "N", or "E" (connection error) String documentHOST = "", SQL = "", refe erHOST = "", retchar="N" ; if (refererURL != null) refererHOST = parseHostFromϋRL (refererURLjI; if (documentURL != null) documentHOST =* parseHostFromURL (documentURL) ; if (documentURL != null) { S Q L = "SELECT author!zed_url PROM Syndicated_Content WHERE pubnow section_name = •" + SectionlD + "' AND active_flg = ' • £' AND pubnow_dbname = ■ " + db + " • AND authorized url LIKE '%" + documentHOST + "%' AND datetime_up < getdateO AND datetime_dowa > getdatej)"; Connection cnn = null; try { cnn = dataConnMan.getConnection(controlServer,controlDb) ; Statement stmt = cnn.createStatement () ; ResultSet rst = stmt.executeQuery (SQL) ; retchar = "N"; while (rst.nextO) retchar = "ϊ"; rst.close () ; stmt.closef) ; dataConnMan.freeConnectιon(controlΞerver,controlDb,cnn) ; ) catch (Exception e) { retchar = "E" ; } } return retchar; } private String parseHostFromURL (String targetURL) { StringTokenizer tokenizer = new StringTokenizer (targetURL, "/"); int tokencount = tokenizer. countTokens () ; int i; String returnHost = ""; if (tokencount > 1) { for (i = 1; i < 3; i++) returnHost = tokenizer.neχtToken() ; ) else { returnHost = ""; } return returnHost; } private String makeArticleHrefs (String HTMLtext) { int i; StringBu er sb = new StringBuf er ( ) ; for (i = 0; i < HTMLtext . length () ; i++) { if ( (HTMLtext. substring (i, x+1) .equals("<") ) s (HTMLtext. substring (i+l,i+ 2 ) . equalsIgnoreCase("a") ) SS (HTMLtext. substring(i+3,i+4) .equals ("H") ) SS (HTMLtext. substring (i+4, i+5) -equals ("r") ) ) { sb.append("<a target=Λ"_blank\"") ; i++; } else { sb. append(HTMLtex . charAt (i) ) ; } ) return sb.toΞtrxng( ) ; ) public long getLast odi ied (HttpServletRequest req) { return lastModified/1000*1000; } . 'private String convertTojs(String HTMLtext, String documentURL, String refererURL) { HTMLtext = HTMLtext.replace ('\r', ' ') HTMLtext = HTMLtext.replacefNn', ' '); try { HTMLtext = swapStrings (HTMLtext, "\\","\\\\") HTMLtext = swapStrings (HTMLtext, "\'","\\V") HTMLtext = swapStrings (HTMLtext, "\"","\\\"") } catch(Exception e) { System,out. rintln(e.getMessage() ) ; ) if (refererURL f= null) { HTMLtext = " if (location.href-indexOf (\"" + documentURL + "\") 1= -1) .{ document.write ('" + HTMLtext + "'); ) else { document. rite {'<BRXB>This web site is not authorized to display the content requested.</B>')/ } "f } else { HTMLtext = " document.write ('" + HTMLtext + "');"; } return HTMLtext; ) B-5 String swapStrings (String Textln, string OldString, String NewString) { int OldStringStartAt; int OldStringLength = OldString.length () ; int NewStringLength = NewString. length () ; String TempText = Textln; OldStringStartAt = indexOfIgnoreCase (TempText, OldString, 0); while (OldStringStartAt != -1) { TempText = TempText. substring( 0, OldStringStartAt) + NewString + TempText. substring (OldStringStartAt + OldStringLength); OldStringStartAt = indexOfIgnoreCase (TempText, OldString, OldStringStartAt + NewStringLength) ; } return TempTex ,- } int indexOfIgnoreCase (String TempText, String substring, int StartAt) { return TempText. toLowerCase ( ) - indexO ( substring. oLowerCase ( ) , StartAt) ; } Content looku (String contentID) { Content cont; int index = -1; for (int i=0; i<contents.size () ; ++i) { cont = (Content) contents. elementAt (i) ; if (contentID. equals (cont. contentID) ) return (Content) contents. elementAt (i) j ) return πull; } class Content { String contentID, detail; long timestamp; Conten (String contentID, String detaxl, long timestamp) { this . contentID = contentlD; this. detail = detail; this. imestamp = timestamp/60000; //converts milliseconds to minutes > } private class Sentinel extends Thread { int itemsToKeep; int minutesToLive; boolean quit = false; Sentinel (int itemsToKeep, int minutesToLive) { . this.itemsToKeep = itemsToKeep; this.minutesToLive = minutesToLive; setPriority (Thread. IN_PRIORITY) ; start () ; } public void run{) { int itemsToRemove; while (iquit) { // this keeps cleanup alive until servlet is destroyed f eshen() ; if (contents. size () > itemsToKeep) trim(); //System. gc () ; try { Thread. sleep(5000) ; } catch (InterruptedException ex) { ) //System.out.println("Ξentinel ran at:" + System. currentTimeMillis () ) ; } private void trimO { int itemsToRemove = contents. size () - itemsToKeep; int trimmed = 0; for (int i=0; i<itemsToRemove; ++i) { contents.removeElementA (i) ; //System,out.println ("Removed: " + contents. elementAt (i) -toStr ngO ) ; Thread. ield () ; trimmed++; ) if (trimmed > 10) contents.trimToSize () ; } private void freshen () { long currentTime = System. currentTimeMillis () /60000; Content cont; for (int i=0; i<contents.sxze () ; ++i) { cont = (Content) contents. elementAt (i) ; if (cont.timestamp + minutesToLive < currentTime) { contents. emoveElementAt (i) ; //System.out.println ("Expired: " + cont.contentID) ; Thread.yield() ,- ) } //Get Servlet information public String getServletlnfof) t return "Retrieves content from PublishNow 2.x databases."; ) B-7 Appendix C * Title: Active Data Syndicator - ADPExport Servlet * Description: Copyright (c) 2001 Active Data Exchange. All rights reserved. * Any use without the express written permission of the copyright * owner is unlawful . * All information contained in the file is confidential to Active Data Exchange * Copyright: Active Data Exchange * Company: Active Data Exchange * Θauthor John E. Wetzel * Θcreation date 10 February 2001 * Slast revision date 13 June 2001 * Sversion 3.01 */ package com. activedatax.products. syndicator.export; import javax. servlet. *,- import java . servlet .http . * ; import java.io.*,- import Java.sql.Connection; import ava .util . StringTokenizer; import Java.util. Properties; import com. activedatax.utils.adxTools; import java .net .URLEncoder; import com. activedatax. sql .HttpServletDb; public class ADPExport extends HttpServletDb { private static String sServer; private static String sDbName; private static String sNoAuthMsg,- private static final String CONTENT_TYPE = "text/html" ; /**Initialize global variables*/ public void init (ΞervletConfig config) throws ServletException { super. init (config) ; File f = new File ( "SyndicatorBG.properties" ) ; if ( ' . exists () ) { f = new File ( "I: /SyndicatorBG/SyndicatorBG.properties" ) ; } Properties dbProps = new Properties ( ) ,- try { InputStream is = new FilelnputStreamff) ,- dbProps .1oad (is) ,- } catch (Exception e) { System. err. rintln( "Can' t read the properties file from ADPExport servlet. " + "Make sure SyndicatorBG.properties is in the CIASSPATH") ; return; } sServer = dbProps .getProperty ("syndicator.database. server" ) ; sDbName = dbProps.getProperty( "syndicator.database.name" ) ; sNoAuthMsg = dbProps . getProperty ( "syndicator.adp.noauthmsg" ) ; } /**Process the HTTP Get/Post request*/ public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String sServerRoot = adxTools.getServerRoo (request) ; String sDocumentURL = " " ; String sTargetURL = " " ,- String sOfferContentSetlds = "0"; Ξtring sltemlds = "0"; String sFullNums = "0"; Striπg sArcNums = "0"; long lOfferContentSetld = 0; long lSerial = 0; long lSubld = 0; C-l long lltemld = 0; int nFullNum = 0; int nArcNu = 0; boolean bNewWindow = false; boolean bShowDates = false; //Serial Number Parameter (required) try { lΞerial = Long. arseLong (request.getParameter ("j3serial") ) ; } catch (Exception e) { lSerial = 0; } //Subscriber Id Parameter (required) try { lSubld = Long.parseLong (request.getParameter ( "j3sub" )) ; } catch (Exception e) { lSubld = 0; } //Offer Content Set Id Parameter (required) sOfferContentSetlds = request.getParameter ("j3ocset") ; if (sOfferContentSetlds == null) sOfferContentSetlds = "0"; //Document URL Parameter (required) sDocumentURL = reques .getParameter ( "j3durl" ) ; if (sDocumentURL == null) sDocumentURL = " " ; SDocumentURL = ADPExporter.removeParamsFromURLIsDocumentURL, "j3serial, j3sub, j3ocset, j3durl, j3itemid, j3fullnum, j3 arcnu , j3 url, j3newwindow, j3showdates, j3rand") ; //Target URL for Archive Links Parameter (optional) sTargetURL = request.getParameter ( "j3turl") ,- if (sTargetURL == null) sTargetURL = sDocumentURL; //defaults to the requesting document //Item Id Parameter per Content Set (optional) sltemlds = request .getParameter ("j3itemid") ; if (sltemlds == null) sltemlds = "0"; //Number of Full Articles to Display per Content Set Parameter (optional) sFulINums = request .getParameter ( "j3fullnum" ) ; if (sFulINums == null) sFulINums = "1"; //default to 1 //Number of Article Archive Links to Display per Content Set Parameter (optional) sArcNums = request .getParameter ( j3arcnum" ) ; if (sArcNums == null) sArcNums = "0"; //default to none //Popup new window when an- archive link is clicked? True or False (optional) try { bNewWindow = (new Boolean (request. etParameter ("j3newwindow") )) .booleanValuef) ; } catch (Exception e) { bNewWindow = false; //default to false } //Show dates along with archive links? True or False (optional) try { bShowDates = (new Boolean(reguest.getParameter ("j3showdates" ))) .booleanValuef) ; } catch (Exception e) { bShowDates = false; //default to false } response. setContentType (CONTENT_TYPE) ; PrintWriter out = response.getWriter () ,- //Expecting these tokenizers to have the same number of tokens. StringTokenizer tokenizer = new StringTokenizer (sOfferContentSetlds, ":") ; StringTokenizer tFull = new StringTokenizer(sFulINums, ":") ; StringTokenizer tArc = new StringTokenizer (sArcNums, ":") ; C-2 StringTokenizer tltems = new StringTokenizer(sItemIds, " : ") ; if (tltems.countTokens () != tokenizer. countTokens () ) { sltemlds = "0"; for tint a=l ; a<tokenizer. countTokens ( ) ;a++) { sltemlds = sltemlds + " : 0" ; ) tltems = new StringTokenizer (sltemlds, ":") ; } Connection cnn = dataConnMan.getConnection(this. sServer, this. sDbName) ; ADPExporter ADP = new ADPExporter (cnn, sServerRoot, ISerial, lSubld, 0, 0, sDocumentURL, sTargetURL, 1, 0, bNewWindow, bShowDates, request. etRemoteAddr ()) ; if (tokenizer. countTokens () > 1) { ADP. setAtomicQueryString(sltemlds, "&j3ocset=" + URLEncoder.encode (sOfferContentSetlds) + "Sj3arcnum=" + URLEncoder. encode(sArcNums) + "&j3fullnum=" + URLEncoder. encode (sFulINums) ) ,- } int nTk = 0; while (tokenizer.hasMoreTokens () ) { try { lOfferContentSetld = Long.parseLong (tokenizer .nextTokenO ) ; try { nFullNum = Integer. arselnt (tFull.nextTokenO ) ; } catch (Exception ex) { nFullNum 1;} try { nArcNum = Integer,parselnt(tArc.nextTokenO ) ,- ) catch (Exception ex) { nArcNum = 0;} try { lltemld = Long.parseLong (tltems.nextTokenO ) ; } catch (Exception ex) { lltemld = 0,-) ADP.setOfferContentΞetΙd(lOfferContentΞetΙd); ADP.setFullNum (nFullNum) ; ADP. setArcNu (nArcNum) ; ADP.setltemld(lIte ld) ; ADP. setAtomicPosition (nTk) ; if (ADP.validateADPRequestO ) { out.println ( DP. getADPContent ( ) ) ; out.println ( "document. rite ( '<P>' ) ; ") ; } else { ou .println ( "document .write ( ' " + this . sNoAuthMsg + "');"); } } catc (Exception e) { out.println! "document.write( '< ! An error occurred while parsing offer content set ids. >');"); } nTk++; } dataConnMan. freeConnection (this .sServer, this .sDbName, cnn) ; ADP = null; out. flush () ,- out . close ( ) ; } public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet (request, response) ,- } /**Clean up resources*/ public void destroy!) { } } C-3 * Title: Active Data Syndicator - ADPExporter Class * Description: Copyright (c) 2001 Active Data Exchange. All rights reserved. * Any use without the express written permission of the copyright * owner is unlawful. * All information contained in the file is confidential to Active Data Exchange * Copyright: Active Data Exchange * Company: Active Data Exchange * Sauthor John E. Wetzel * Θdate 10 February 2001 * Θlast revision date 21 June 2001 * (aversion 3.01 */ package com.activedatax.products . syndicator. export; import com.activedatax.utils.adxURLParser; import Java .util . StringTokenizer,- import ava .net .MalformedURLException; / /import com. imaginary.lwp.Identifier; import com. ctivedatax.products. syndicator .content.OutputType; import java.io.OutputStream; i port Java.net.URLEncoder; import java.io.FileOutputStream; import java.io.IOException; import Java.util. ist; import java.rmi.RemoteException; import Java.util. Iterator; import ava.util.Date; i port ava.util.Collection- import Java .util . StringTokenizer; import Java.util .Hashtable; import java .sql . * ,- import java . text . SimpleDateFormat; import javax.servlet. ttp.HttpServletResponse; import com.activedatax. tils .DigraphEncrypt; import com. activedatax.utils.adxTools; import gn . regexp . * ; /* * This class is a helper class for the ADPExport servlet. */ class ADPExporter { // class variables/objects private Hashtable hltems; private Hashtable hltemContent; private Connection cnn; private String sServerRoot, sDocumentURL, sTargetURL, sAtomicQueryString, sIPAddress, sltemTokens ,- private long lSerial, lSubld, lOfferContentΞetld, IContentSetId, l temld; private int nPos; private boolean bNewWindow, bShowDates; int nFullNum, nArcNum, nltemHashSize; ADPExporter (Connection pCnn, String psServerRoot, long plSerial, long plSubld, long plltemld, long plOfferContentSetld, String psDocumentURL, String psTargetURL, int pnFullNum, int pnArcNum, boolean pbNewWindow, boolean pbShowDates, String psIPAddress) { // init class variables/objects this.cnn = pCnn; this.lSerial = plSerial ; this.lSubld = plSubld; this. lltemld = pl te ld; this.sServerRoot = psServerRoot; this.lOfferContentSetld = plOfferContentSetld; this . IContentSetId = this.lOfferContentSetld; this . sDocumentURL = psDocumentURL; C-4 this .sTargetURL = psTargetURL; this.nFullNum = pnFullNum; this.nArcNum = pnArcNum; this.bNewWindow = pbNewWindow; this.bShowDates = pbShowDates; this.sIPAddress = psIPAddress; this.sAtomicQueryString = " " ,- this . sItemTokens = " " ; this.nPos = -1; } public void setFullNum(int pnFullNum) { this.nFullNum = pnFullNum; ) public void setArcNumfint pnArcNum) { this.nArcNum = pnArcNum; } public void setltemldflong plltemld) { this.lltemld = plltemld; } public void setOfferContentSetldflong plOfferContentSetld) { this . lOf erContentSetld = plOfferContentSetld; } public void setAtomicQueryString (String psltemlds, String psAtomicQueryString) { this.sAtomicQueryString = psAtomicQueryString; this.sIte Tokens = psltemlds ; } public void setAtomicPositiondnt pnPos) { this.nPos = pnPos; } ** * This method will check to see if the web site making the content request is * authorized to receive the content. */ public boolean validateADPRequest () { String sSQL = " " ; String sURL = parseHostFromURL(this. sDocumentURL) ; boolean bAuthorized = false,- PreparedStatement stmt; ResultSet rs; //A non-subscriber is requesting the content. //The value in pOfferContentSetld refers to the "content_set_id" column of the content_set :able. if {(this.lSerial == -1) S& (this.lSubld == -1)) { this . IContentSetId = this.lOfferContentSetld; sSQL = "SELECT DISTINCT url.url_id, url.crt_class FROM url, content_set " + "WHERE content_set.content_set_id = ? " + "AND UPPER(url.url) LIKE ? " + "AND url.url_id NOT IN (SELECT DISTINCT url_id FROM subscriber_url) " + "AND url.site_id = content_set.site_id "; try { stmt = cnn.prepareStatement (sSQL) ; stmt. clearParameters ( ) ; stmt . setLong (1, this . IContentSetId) ; stmt.setstring( 2 , "%" + sURL.toUpperCase + "%"),- stmt . setMaxRows (1) ; rs = stmt.executeQueryO ; while (rs.nex () ) { bAuthorized = true; } rs.close () ; stmt.closet) r } catc (Exception e) { C-5 e.printΞtackTrace ; ) //A subscriber is requesting the content. ) else { sSQL = "SELECT DISTINCT url.url_id, url.crt_class FROM url, offer_content_set, " + "subscription_subdetails, subscriber, subscriber_url " + "WHERE (offer_content_set . of er_content_set_id = ? " + "AND subscription_subdetails.serial_.no = ? " + "AND subscriber. subscriber_id = ? " + "AND subscriber_url . subscriber_id = ? " + "AND url.url like ?) " + "AND offer_content_set.offer_id = subscription_subdetails.offer_id " + "AND subscription_subdetails.subscriber_id = subscriber. subscriber_id " + "AND subscriber. subscriber_id = subscriber_url.subscriber_id " + "AND subscriber_url.url_id = url.url_id"; try { stmt = cnn.prepareStatement (sSQL) ,- stmt.clearParameters ( ) ; stmt. setLong(1, this . lofferContentSetld) ; stmt .setLong(2, this .lSerial) ; stmt. setLong (3, this .lSubld) ; stmt. setLong ( , this. lSubld) ; stmt.setstring{5, "%" + sURL. toUpperCaseO + " "),- stmt . setMaxRows (1) ,- rs = stmt.executeQuery () ; while (rs.next () ) { bAuthorized = true; } rs. closet) ; stmt. close ( ) ; } catch (Exception e) { e.printStackTraceO ; } } return bAuthorized; } ** * This method retrieves the requested content as defined by this classes' parameters. */ private void getltemHashDataO { this.nltemHashSize = Math. abs (this .nFullNum) + Math. abs (this.nArcNum) ; this.hltems = new Hashtable (this.nltemHashSize) ; this.hltemContent = new Hashtable! this.nltemHashSize) ; PreparedStatement stmt; ResultSet rs; String sSQL = "", sltemReview = "N", sltemlds = ""; StringU sTemp = {"","", »« , »» , »» , »» , »» , »» , »» , »» } ; long lThisItemld; int nAllowedArcNum = 0; int nFullCount = 0; int nResultCount = 0; if ( ! ( (this.lSerial == -1) &&: (this.lSubld == -1))) { // A subscriber has requested the content . //get the necessary content_set_id with an additional query sSQL = "SELECT offer_content_set . content_set_id, subdetails_cs. archives, subdetails_cs.item_review " + "FROM of er_content_set, subdetails_cs " + "WHERE subdetails_cs.serial_.no = ? " + "AND subdetails_cs . of er_content_set_id = ? " + "AND subdetails_cs . output_type_id = ? " + "AND subdetails_cs . offer_content_set_id = offer_content_set.offer_content_set_id" try { stmt = cnn.prepareStatement (sSQL) ; stmt .clearParameters ( ) ; stmt. setLong (1, his.lSerial) ; C-6 stmt. setLong(2, this. lOfferContentSetld) ; stmt.setInt(3,OutputType.ADP) ; stmt.setMaxRows (1) ; rs = stmt.executeQuery!) ; while (rs.nex () ) { this . IContentSetId = rs .getLong (l) ; nAllowedArcNum = rs . getlnt (2 ) ; sltemReview = rs .getString (3 ) ,- } rs . close t) ; stmt. close ( ) ; catch (Exception e) { System.err .println C'An ERROR ocurred in ADPExporter . . . " ) ; e.printStackTrace ( ) ; return ; } //make sure the subscriber hasn't tried to request more archives than allowed if (nAllowedArcNum < this.nltemHashSize) this.nltemHashSize = nAllowedArcNum; } if (sltemReview. equals ("Y") ) { return; //will need to code a block here when item_review feature is added } String sCsId = "AND item_content_set.content_set_id = ? "; if (this. IContentSetId == -1) sCsId = "AND item.item_id = ? //now get the content set items (not including the actual content column) sSQL = "SELECT item. item_id, item. title, item. subtitle, item. author, item.byline, " + "item.link_text, item.meta_data, item. comments, item.inctitle, item.last_updated_on + "FROM item, item_content_set " + "WHERE UPPER(item. status) != ? AND item.timeup <= ? " + "AND item.timedown >= ? " + "AND item.item_id = item_content_set .item_id " + sCsId + "ORDER BY item.timeup DESC "; try { stmt = cnn.prepareStatementfsSQ ) ; stmt . clearParameters ( ) ,- stmt.setStringd, "D") ,- stmt.setτimestamp(2,new Timestam ( (new DateO ) .getTimet) ) ) ; stmt.setτimestamp(3,new Timestam ( (new DateO ) -getTime ())) ; if (this. IContentSetId > -1) stmt.setLong(4, this. IContentSetId) ; else stmt. setLong(4, this.lltemld) ,- stmt. setMaxRows (this.nltemHashSize) ; rs = stmt.executeQuery () ; while (rs.next () ) { IThisItemId = rs.getLong(l) ; System, out.println ("FOUND ITEM ID: " + IThisItemId) ,- i (this.nFullNum > nFullCount) { if (nFullCount > 0) sltemlds = sltemlds + ","; sltemlds = sltemlds + String .valueOf (IThisItemId) ; nFullCount++; } sTempfO) = String. alueO (IThisItemId) ; //item_id sTemptl) = rs.getString(2) ; //title sTemp[2] = rs.getString(3) ; //subtitle if(sTemp[2] == null) sTemp[2J = " » ; sTemp[3] = rs.getString(4) ; //author if(sTemp[3] == null) sTemp[3] = ""; sTemp[4] = rs.getString(5) ; //byline if(sTemp[4) == null) sTemp[4] = ""; sTemp(5] = rs.getstring(6) ; //linktext if(sTemp[5) == null) sTemp[5] = " " ,- sTemptδ] = rs.getString(7) ; //metadata C-7 if (sTemp[6] == null) sTemp[6] = "",- sTemp(7] = rs.getString(8) ,- //comments if(sTemp[7) == null) sTemp[7) = "",- sTemp[8] = rs.getString (9) ; //inctitle sTempt9) = rs.get imestamp(lθ) . toStringO ; //displaydate this. hlte s .put (String. valueOf (nResultCount) , sTemp.clone( ) ) ; nResultCount++ ,- } rs. close () ; stmt. close! ) ; } catch (Exception e) { System. err. println("An ERROR ocurred in ADPExporter ..."); e.printStackTrace! ) ; } //finally get nFullNum number of item "content" fields or a specific item if ( (sltemlds. length!) > 0) || (this. lltemld > 0)) { if (this. lltemld > 0) { //a specific item link was clicked on sSQL = "SELECT item_id, content FROM item WHERE item_id =" + String. alueOf (this. lltemld) ; } else { sSQL = "SELECT item_id, content FROM item WHERE item_id IN(" + sltemlds + ")"; } try { stmt = cnn.prepareStatement (sSQL) ; stmt.clearParameters ( ) ; rs = stmt.executeQuery!); while (rs. next () ) { this.hltemContent.put (new Long(rs.getLong(l) ) , rs.getString (2) ) ; } rs. close! ) ; stmt. close!) ; } catch (Exception e) { System. err. rintln( "An ERROR ocurred in ADPExporter ..."); e.printStackTrace () ; } } } public String getADPContent ( ) { getltemHashDatat) ; String sURL = ( his.sTargetURL.indexOf ("?") == -1) ? "?" : "S:"; String sNewWindow = (this.bNewWindow) ? " TARGET=\ "_new\ " " : " " ,- String sLink, sContent, ΞDisplayDate, sltemldParameter; StringBuffer cb = new StringBuffer ("") ; //content buffer StringBuffer lb = new StringBu fer {"") ; //link buffer String [] sTemp; int nFull = this.hltemContent. size () ; int nltems = this. ltems. size () ,- boolean bNegativeArcNu = (this.nArcNum < 0) ; // j3serial, j3sub, j3ocset, j3durl, j3itemid, j3fullnum, j3arcnum, j3turl, j3newwindow,j3showdates, 3rand if (this.sAtomicQueryString.length() > 0) { sURL += "j3serial=" + URLEncoder. encode (String. alueOf (this.lSerial) ) + "&j3sub=" + URLEncoder. encode (String.valueOf (this.lSubld) ) + this.sAtomicQueryString + "&j3newwindow=" + URLEncoder.encode (String .valueOf (this .bNewWindow) ) + "&j3showdates= " + URLEncode . encode (String. alueO (this .bShowDates) ) ; } else { sURL += "j3serial=" + URLEncoder. encode (String. alueOf (this.lSerial) ) + "&j3sub=" + URLEncoder. encode (String. alueOf (this. lSubld) ) + "&j3ocset=" + URLEncoder.encode (String .valueOf (this.lOfferContentSetld) ) + "&α'3arcnum=" + URLEncoder. encode(String.valueOf (this.nArcNum) ) + "Sj3newwindow=" + URLEncoder.encode (String.valueOf(this.bNewWindow) ) + C-8 "&j3showdates=" + URLEncoder. encode (String. valueOf (this. bShowDates) ) ; for (int i=0; i<nltems; i++) { sTemp = (String!] ) this. hltems. getfstring. valueOf (i) ) ; sContent = (String) this. hltemContent. get (new Long ( sTemp ( 0 ] ) ) ; if(sContent != null) { sContent = replaceltemBinaryRefs (sContent) ; //sContent = adxTools. swapStrings (sContent, "\u00f3\u00f3" , this. sServerRoot + "com. activedatax. products. syndicator. export. ADPRetrieveItemBinary?binary_id=") ; } else { sContent = " " ,- } sLink = (sTem [5] .trim() .length () > 0) ? sTemp[5) . trim() : sTemp[l] . trim() ; sDisplayDate = sTemp[9]; i (this.bShowDates || bNegativeArcNum) { sDisplayDate = SDisplayDate. substring (5, 7) + "/" + sDisplayDate. substring(8, 10) + "/" + sDisplayDate. substring(2, 4) ; sLink += " (" + sDisplayDate + ")"; } //sTemp[0] item_id //sTemp[l] title //sTemp[2] subtitle //sTemp[3] author //sTemp[4] byline //sTemp[5] linktext //sTemp[6] metadata //sTempf7) comments //sTemp[8] inctitle //sTemp[9] displaydate sltemldParameter = sTemp[0]; //the current item_id if (this.sAtomicQueryString. length!) > 0) { StringTokenizer tltems = new StringTokenizer (this. sltemTokens, ':"); if(this.nPos == 0) { sltemldParameter = sTemp[0]; tltems .nextToken ( ) ; ) else { sltemldParameter = tltems.nextToken 0 ; } int nq = 1; while (tltems.hasMoreTokens () ) { if (this.nPos == nq) { sltemldParameter += + sTemp [ 0 ] ; tltems .nextToken ( ) ; } else { sltemldParameter += + tltems. nextTokenO ; } nq++; if (sContent. length () > 0) { cb. append (sContent + "<p>"); if (Math. abs(this. nArcNum) > 0) if (( 'this. bNewWindow) || ( (this. bNewWindow) S& (this.l temld==0) ) ) lb. append (sLink + "<BR>"); } else { i (Math. abs(this. nArcNum) > 0) if ( (!this. bNewWindow) || ( (this. bNewWindow) S& (this.lltemld==0) ) ) lb . append (" <A • HREF=\"" + this . sTargetURL + sURL + "S:j3itemid=" + URLEncoder .encode (sltemldParameter) + i " Λ sNewWindow + ">" + sLink + "</A><BR>"); ) } // end for return parseConten (cb.toStringO + "<P>" + lb.toStringO + "<P>", » "),- } private String replaceltemBinaryRefs (String pεContent) { StringBuffer sb = new StringBu er(psContent.length() + 300); C-9 String Sid; int nPos = 0; int nLoc = psContent.indexOf ("\u00f3\u00f3") ; while (nLoc != -1) { sb.append(psContent.substring(nPos,nLoc) ) ; sld = adxTools.convertStringToHexString(DigraphEncrypt.encryptDiGraph( this.sIPAddress + "TFB" + psContent. substring (nLoc+2,nLoc+22) ) .trim() ) ; sb.appen (this. sServerRoot + "com.activedatax.products. syndicator.export.ADPRetrieveItemBinary?binary_id=" + sld) ; nPos = nLoc + 22; nLoc = psContent. indexOf ( "\u00f3\u00f3" ,nPos) ; } sb. append (psContent. substring (nPos) ) ; return sb. toString ( ) ; } ** * This method will remove specified querystring parameters from a supplied URL * and return the resulting URL * * Example: For the method parameters * psURL = "http: //www.mysite. com/page. asp?paraml=x&param2=y&param3=z" * psQueryStringParams = "paraml,param3" * * The returned URL will be: * "http: //ww .mysite.com/page.asp?param2=y" */ public static String removeParamsFromUR (String psURL, String psQueryStringParams) { //System.out .println (URL) ; String sTempURL = psURL; StringTokenizer tokenizer = new StringTokenizer (psQueryStringParams, ",") ; adxURLParser myParser = new adxURLParser () ; try { while (tokenizer .hasMoreTokens () ) { myParser. setOriginalUR (sTempURL) ; myParser .setParamToRemove(tokenizer.nextToken () ) ; sTempURL = myParser.getRemovedParamUR O ,- } ) catch (MalformedURLException mue) { mue.printStackTrace!) ,- //return an error string that will need to be handled by the calling method. sTempURL = "error"; } return sTempUR ; } ** * This method will parse out and return the host/domain name from a supplied URL * * Example: For the URL: * psURL = "http://www.mysite.com/page.asp?paraml=x&param2=y&param3=z" * * The returned String will be: * "www.mysite.com" */ public static String parseHostFromURL (String psURL) { StringTokenizer tokenizer = new StringTokenizer (psURL, "/"),- int tokencount = tokenizer.countTokens () ; int i; String sReturnHost = " " ; try { if (tokencount > 1) { for (i = 1; i < 3; i++) sReturnHost = tokenizer.nextTokenf) ,- } else { sReturnHost = "error" ; } } catch(Exception e) { C-10 //return an error string that will need to be handled by the calling method. sReturnHost = "error" ,- } return sReturnHost,- ) public static int indexOfIgnoreCase (String sTempText, String sSubString, int nStartAt) { return sTempText . toLowerCase ( ) . indexOf ( sSubString. toLowerCase ( ) , nStartAt) ; > /* public static String swapStrings (String sTextln, String sOldString, String sNewString) { int nOldStringStartAt; int nOldStringLength = sOldString.length!) ; int nNewStringLength = sNewString.lengthf) ,- String sTempText = sTextln; nOldStringStartAt = indexOfIgnoreCase (sTempText, sOldString, 0) ; while (nOldStringStartAt != -1) { sTempText = sTempText. substring) 0, nOldStringStartAt) + sNewString + sTempText. substring (nOldStringStartAt + nOldStringLength) ; nOldStringStartAt = indexOfIgnoreCase (sTempText, sOldString, nOldStringStartAt + nNewStringLength) ; } return sTempText; } */ public static String parseContent (String sContent, String sServerRoot) { String sClientScripts = " " ; int nStartSearchAt = 0; int nScriptLoc = indexOfIgnoreCase (sContent, "<SCRIPT" ,nStartSearchAt) ; if (nScriptLoc > -1) { //Check for client scripts and separate them from regular HTML try { int nEndScriptLoc,- int nArticleLength = sContent. length () ,- StringBu fer sbArticle = new StringBuffer (nArticleLength + 1) ; StringBu fer sbScripts = new StringBuffer () ; while (nScriptLoc > -1) { nEndScriptLoc = indexOfIgnoreCase (sContent, ,r </SCRIPT>" ,nScriptLoc) ; sbArticle.append(sContent.substring (nStartSearchAt, nScriptLoc) ) ; sbScripts . appen (sConten . substring ( (indexOfIgnoreCase (sConten , " >" , nScriptLoc) +1) , nEndScriptLoc) ); sbScripts .append( ' \n' ) ; sbScripts .appen ( ' \r' ) ; //System. out.println ("The HTML: " + sContent. substring (nStartSearchAt,nScriptLoc) ) ; //System. out.println("The Script: " + sContent.substring! (indexOfIgnoreCase (sContent, ">" .nScriptLoc) +1) , nEndScriptLoc) ) ; nStartSearchAt = nEndScriptLoc + 9; nScriptLoc = indexOfIgnoreCase (sContent, "<SCRIPT" ,nStartSearchAt) ; } //sbArticle.append(sContent.substring (nStartSearchAt,nArticleLength - 1) ) ; sbArticle.append(sContent. substring (nStartSearchAt,nArticleLength) ) ; //changed by JW //System. out. rintln (sbArticle. oString ) ; //System. out.println (sbScripts. oΞtringO ) ; sClientScripts = sbScripts . toString () ; //contains just the scripts' code sContent = sbArticle. toString (> ; //contains just the article HTML } catch (Exception e) { • System. err.println(e.getMessage() ) ; e.printStackTrace () ;, ) } sContent = sContent.replace { '\r' , ' '); sContent = sConten .replace( ' \n' , ' ' ) ; try { sContent = adxTools. swapStrings (sContent, "\\" , "\\\\") ; C-ll sContent = adxTools. swapStrings (sContent, "V ", "\W ") ; sContent = adxTools.swapStrings (sContent, "\" ", "\\\" ") ,- } catch(Exception e) { System.err. rintlnfe.getMessage!) ) ; e .printStackTrace ( ) ; } return sClientScripts + " document. rite ('" + sContent + " ' ) ; " + ' \r } // end class ADPExporter C-12 Appendix D fαctive dαfα exchange CONTENT. ANY PLACE. ANYTIME. ACTIVE DATA RANDOMIZER User Guide Active Data Randomizer gives Users the power to keep a Website fresh and inviting to visitors. This convenient, easy-to-use tool facilitates the collecting, grouping, modifying and removal of messages, either graphic or text, that are displayed within a page each a time it is loaded, reloaded or refreshed by the viewer. This User Guide is an overview of how Active Data Randomizer works and what it does. For a complete demonstration, contact you Active Data -Exchange representative. (active data exchange Active Data Exchange, Inc. 190 Brodhead Road, Suite 300 Bethlehem, PA 610.997.8100 www.activedatax.com D-l uacTive σαto exchange CONTENT. ANY PLACE. ANYTIME. Table of Contents Overview 3 Step-by-step guide for Active Data Randomizer 3 Getting Started 3 Step 1 Site Set Up 4 To Set up a new site 4 Step 2 Randomizer Groups 4 Step 3 HTML Blurbs 6 To add another HTML blurb: 7 Step 4 Java Script Code 7 Step 5 Verify or Modify Blurb Groupings 9 Step 6 Rotating Blurbs for Preview 10 Step 7 Exit 10 Table of Figures Figure 1 Site Configuration Screen 3 Figure 2 Add a New Site Configuration 4 Figure 3 Add a New Group Name 5 Figure 4 New Group Confirmation Message 5 Figure 5 New Active Data Randomizer Blurb Group 6 Figure 6 New Active Data Randomizer Blurb HTML Confirmation 7 Figure 7 Active Data Randomizer Blurb Code 8 Figure 8 Sample HTML Editor 8 Figure 9 Confirmation and View Message Window 9 D-2 (active data YOUR CONTENT. ANY PLACE. ANYTIME. exchange Active Data Randomizer User Guide Active Data Randomizer Overview A practical tool, Active Data Randomizer gives Users the power to keep their Website viewers attentive to the screen by changing a specific part of a page message each time a viewer refreshes or returns to a previously viewed screen. An easy to use tool that requires no additional hardware or installation, Active Data Randomizer is platform independent and facilitates the grouping and presenting of graphic or text messages on a Website page. The Active Data Randomizer allows for direct, targeted message updates, without the complexities of publishing completely new pages or documents, from any location with Internet access, at any time. Short, catchy visuals and text can be displayed on a page with little effort on the part of the client after setup is complete. The random display of messages keeps your page continually altering and fresh to viewers as they browse through a site. Using Active Data Randomizer to rotate images or messages will decrease the static look and feel of a Web page. Step-by-step guide for Active Data Randomizer Getting Started The Active Data Randomizer is accessible through a Universal Resource Locator, URL. Open your Internet browser and enter this URL into the proper area: http://publisher3.activedatax.com/servlet/com.activedatax.products.Blurb.AdminMenu You will be taken to the main screen for Active Data Randomizer. Active Data Randomizer j Site Configuration Options • Add a New Site Configuration • Change a Site Configuration • Delete a Site Configuration • Generate a Site's Administration Code Site Blurb Functions for Blurb Demo Add a New Group Delete a Group View Groups Add a New HTML Blurb View. Modify or Delete HTML Blurbs Generate Blurb Code Figure 1 Site Configuration Screen Active Data Exchange. Page 3 www.activedatax.com This document contains confidential information. No part of this document maybe be reproduced or transmitted, in any form or by any means without the express written permission of Active Data Exchange. ©Copyright 2001, all rights reserved. D-3 (α livc α.α YOUR CONTENT. ANY PLACE. ANYTIME. exchange Active Data Randomizer User Guide The main screen for the Active Data Randomizer has links to each and every functionality offered by this time-saving tool. Once you have accessed the Active Data Randomizer tool, you will see all the site configuration options and functions that are usable for screen refresh messages. Click on any of the bulleted items to access that functionality. Step l Site Set Up You will arrive at this window when Add a New Site Configuration is chosen from the Site Configuration Screen. From here you are able to set up a new location to display Active Data Randomizer messages or return to the Menu. Figure 2 Add a New Site Configuration To Set up a new site 1. Site Name— enter your new site name. 2. Descriptions — enter a brief explanation. 3. Enter the URL to locate the site and the page where you want your dynamic blurbs to be displayed 4. Select the Submit Configuration button The new site is automatically configured, and you will be returned to the Administration screen. NOTE— the success of your new site set-up is confirmed and expressed by the red text in the upper portion of the screen. Step 2 Randomizer Groups You will arrive at this window when Add a New Group is chosen from the Site Configuration screen. From here you are able to set up a new group of Active Data Randomizer blurbs or return to the Menu. Active Data Exchange. Page 4 www.activedatax.com This document contains confidential information. No part of this document maybe be reproduced or transmitted, in any form or by any means without the express written permission of Active Data Exchange. ©Copyright 2001, all rights reserved. D-4 (active data YOUR CONTENT. ANY PLACE. ANYTIME. exchange Active Data Randomizer User Guide Figure 3 Add a New Group Name 1. Enter a Group Name for your first collection of different blurbs that will be used for a specific location. These are the dynamic blurbs that will be rotated sequentially every time a viewer returns to that page and it is reloaded, or when the viewer selects the refresh icon. The blurbs you want to set up are virtually limitless and can be graphic or textual based. The sample group name in this case is 02blurb test. 2. Click Submit Group. Active Data Randomizer Administration The new blurb group 02bfurb test was added to the Blurb Demo site Site Configuration Options • Add a Hew Site Configuration • Change a Site Configuration • Delete a Site Configuration • Generate a Site's Administration Code Site Slurb Functions for j] • Add a Hew Group • Delete a Group • View Groups . Add a Hew HTML Blurb » View. Modify or Delete HTML Blurbs • Generate Blurb Code Figure 4 New Group Confirmation Message 3. You will be returned to the main menu. A confirmation that your group has been created is shown in red text. It repeats the Group Name and the Site Name that it has been added to. 4. To continue click on Add a New HTML Blurb, located in the lower group of bulleted items. Active Data Exchange. Page 5 www.activedatax.com D-5 (active data YOUR CONTENT. ANY PLACE. ANYTIME. exchange Active Data Randomizer User Guide Step 3 HTML Blurbs You will arrive at this window when Add a New HTML Blurb is chosen from the New Group Confirmation screen. From here you are able to set up a new location to display Active Data Randomizer messages or return to the Menu. Figure 5 New Active Data Randomizer Blurb Group From the Add a New randomizer screen, select the Group Name from the pull down menu you want this new HTML blurb added to. Enter or Copy and Paste the HTML code for the picture or text or both that you want to show in the refreshed window. This information is retrieved from your original document's source code from whatever HTML editor program you are using. Active Data Exchange. Page 6 www.activedatax.com This document contains confidential information. No part of this document maybe be reproduced or transmitted, in any form or by any means without the express written permission of Active Data Exchange. ©Copyright 2001, all rights reserved. D-6 (active data YOUR CONTENT. ANY PLACE. ANYTIME. ange Active Data Randomizer User Guide Figure 6 New Active Data Randomizer Blurb HTML Confirmation 3. Click on Submit Blurb. A confirmation screen will show that the blurb has been added. You are still able to modify or delete your blurb in the future if necessary. Any action you take at this step will be confirmed within the next window in red text. To add another HTML blurb: 1. Click on [Copy] and Randomizer will automatically duplicate your last HTML blurb. 2. Either insert new HTML text or alter your HTML text, as in the case of changing the image only, you can just update the name of the source image, without having to re-enter all new HTML. 3. Select the Submit Blurb button after each entry to save the changes Each entry will be confirmed and added to your list of HTML blurbs. 4. Repeat this process until you have added all your HTML blurbs. 5. Select Go Back to Menu. Step 4 Java Script Code Once you have returned to the Site Configuration main screen, 1. Select Generate Blurb Code from the lower level bulleted options. 2. Active Data Blurb Admin will automatically write the Java Script needed to instruct your site to sequentially rotate the HTML sources. This Java will include all necessary instructions to refresh the image in the window each time it is reloaded or manually refreshed. Active Data Exchange. Page 7 www.activedatax.com This document contains confidential information. No part of this document maybe be reproduced or transmitted, in any form or by any means without the express written permission of Active Data Exchange. ©Copyright 2001, all rights reserved. D-7 (active data YOUR CONTENT. ANY PLACE. ANY TIME. efcξhange Active Data Randomizer User Guide Figure 7 Active Data Randomizer Blurb Code 3. Highlight and copy this Java Script 4. Return to your primary source document using your HTML Editing program and select the HTML source view. %s^ mmm α < Figure 8 Sample HTML Editor Paste the Active Data Randomizer Java script you have copied into your original source document for the Web page. Active Data Exchange. Page 8 www.activedatax.com This document contains confidential information. No part of this document maybe be reproduced or transmitted, in any form or by any means without the express written permission of Active Data Exchange. ©Copyright 2001, all rights reserved. D-8 (active data YOUR CONTENT. ANY PLACE. ANYTIME. eXξharuje Active Data Randomizer User Guide NOTE — ake sure you are within the proper location on your Web page. Paste the script in the exact position where you want the message to be displayed on the page. 6. Exit (or close) your HTML editing program and return to the Active Data Randomizer Administration screen. 7. Click the Return to Menu button. Step 5 Verify or Modify Blurb Groupings From the main Active Data Randomizer Administration window, you may view your group of messages. Active Data Randomizer presents both the HTML and a visual of the output. 1. Choose the View. Modify. Delete HTML Blurb to view and confirm your message or messages. Figure 9 Confirmation and View Message Window A preview image of the actual image that will be shown on a viewer's screen. Select Go Back to Menu to pretest the messages. Active Data Exchange. Page 9 www.activedatax.com This document contains confidential information. No part of this document maybe be reproduced or transmitted, in any form or by any means without the express written permission of Active Data Exchange. ©Copyright 2001, all rights reserved. D-9 (acib i Kϊ dάta YOUR CONTENT. ANY PLACE. ANYTIME. e Hξξhhααni cje Active Data Randomizer User Guide Step 6 Rotating Blurbs for Preview It is best to always pretest the site to make sure your messages are being presented properly. 1. Open any separate browser window and point to the page you want to check. 2. Choose refresh to view the new message in the Group you have been assigned to that page. Continue to choose refresh or move to another page and return to the original page to verify that your messages have changed. At times it is normal for Active Data Randomizer to repeat a message or image. 3. Exit Step 7 Exit Users may exit Active Data Randomizer Administration by simply leaving or closing your browser window. About Active Data Exchange Active Data Exchange is a leader in syndication software solutions that empower companies to get the right content to the right place at the right time. Active Data Exchange helps create highly effective information delivery chains with partners, customers, vendors, distributors, investors, and other target groups and affects commerce with communications tools better than existing email technologies. The company is active in several industry standards committees including the Information and Content Exchange Authoring Group and the W3C XML Protocol Standards Committee. Clients include Crown, Cork and Seal, MainStreet Networks, Turner Construction, Penn Mutual Life Insurance, DeSales and Lehigh University. Active Data Exchange. Page 10 www.activedatax.com This document contains confidential information. No part of this document maybe be reproduced or transmitted, in any form or by any means without the express written pemission of Active Data Exchange. ©Copyright 2001, ail rights reserved. D-10 Appendix E /** * Title: Active Data Blurb Machine<p> * Description: Dynamic HTML content generation without the need for a client install.<p> * Copyright: Copyright (c) John E. Wetzel<p> * Company: Active Data Exchange, Inc.<p> * Θauthor: John E. etzel * Sversion: 1.0a */ package com.activedatax.products .Blurb; import javax. servlet.*; import javax. servlet.http.*; import com.activedatax. roducts .Blurb.dbmodules . *; import com.activedatax.products.Blurb.html. *,- import com.activedatax. sql.HttpServletDb; import com.activedatax.utils .HTMLQuoter; import java.io.*; import java.net. * ; import Java.util. *,- import Java. sql.*; import gnu.regexp. * ; import Java.net.URL; public class AdminMenu extends HttpServletDb { private BlurbCommon mycommon; private String server = " " ; private String dbname = " " ; private String thisServlet = " " ; private String serverRoot = "",- private String fLink = " " ,- private String Post = ""; //Initialize global variables public void init (ServletConfig config) throws ServletException { super. init (config) ; //USE BlurbCommon. class TO GET PROPERTIES — SERVER & DATABASE NAME mycommon = new BlurbCommon ( ) ; Properties p = mycommon. getProps () ; serverRoot = p . getProperty ( "server.root" ) ; server = p.getProperty ( "default. server" ) ; dbname = p.getProperty ( "default.dbname" ) ; //store the alias in p = mycommon.getAliases () ; thisServlet = p. getProperty( "AdminMenu") ; fLink = serverRoot + thisServlet; Post = serverRoot + thisServlet; } public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String outputHTML = doBlurb (request, response, this.fLink, this.fPost, false); response.setContentType ( "text/html" ) ; PrintWriter out = response.get riter () ; //System.out. rintl (request.getParameter ( "jbact" ) ) ; out.println (outputHTML) ; retur ; } public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String outputHTML = doBlurb(request, response, this.fLink, this.fPost, false); response. setContentType ( "text/html" ) ; PrintWriter out = response.getWriter() ; out. rintln (outputHTML) ; return; E-l } public String doBlurb(HttpServletRequest request, HttpServletResponse response, String forwardLink, String forwardPost, boolean syndicated) throws ServletException, IOException { int jbsid, jbgid, jbbid; String outputHTML = " " ; String param = " " ,- String action = request. getParameter ( "jbacfc") ; try { jbsid = Integer. parselnt (request . getParameter ( "jbsid" ) , trim ( ) ) ; } catch (Exception e) { jbsid = -1 ; } try { jbgid = Integer.parselnt (request.getParameter ("jbgid") .tri O ) ; } catch (Exception e) { jbgid = -1; } try { jbbid = Integer,parselnt (request. getParameter ( "jbbid") .trimO) ; } catch(Exception e) { jbbid = -1; ) if (jbsid == -1) { //get the blurb_site_id of the first site in the drop-down list box jbsid = getFirstSitel O ; } if ((action == null) || (action. length () == 0)) { outputHTML = AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , " " , syndicat ed); } else { if (action. equalslgnoreCasef "add") ) { outputHTML = AdminMenuHTML. siteAddOrModify(forwardLink, -1, »» , »» , "http://" , "") ,- } else if (action. equalsIgnoreCase( "addpost") ) { outputHTML = doSiteAdd (request, response, syndicated); } else if (action. equalsIgnoreCase("getpostdata" ) ) { outputHTML = AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , " ", syndicat ed); } else if (action. equalsIgnoreCase ( "addbg" ) ) { outputHTML = AdminMenuHTML.groupAdd(jbsid,-l, forwardLink, forwardPost, "", getSiteNameFromld (jbsid) , "") ; } else if (action. equalsIgnoreCase ("addbgpost") ) { outputHTML = doGroupAdd (request, response, forwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase ("addbb") ) { outputHTML = addBlurb( bsid, orwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase ( "copybb" ) ) { outputHTML = copyBlurb(jbsid, jbgid, jbbid, forwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase ("chgbb") ) { outputHTML = changeBlurb (jbsid, jbgid, jbbid, forwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase! "chgbbpost2 " ) ) { outputHTML = doBlurbChange (request, response, forwardLink, forwardPost, syndicated) ; } else if (action.equalsIgnoreCase ( "addbbpost") ) { outputHTML = doBlurbAdd(request, response, forwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase ("chg" ) ) { outputHTML = changeSiteSelect (syndicated) ; } else if (action. equalsIgnoreCase ("gensitecode") ) { outputHTML = genSiteCodeSelect (syndicated) ; } else if (action. equalsIgnoreCase ("gensitecodepostl") ) { outputHTML = AdminMenuHTM .generateSiteAdminCode (jbsid, forwardLink, this . serverRoot,getSiteNameFromld (jbsid) ) ; } else if (action. equalsIgnoreCase ( "chgpostl" ) ) { outputHTML = changeSiteDetails (request, response, syndicated) ; } else if (action. equalsIgnoreCase ("chgpost " ) ) { outputHTML = doSiteChange (request, response, syndicated); } else if (action. equalsIgnoreCase ("del" ) ) { outputHTML = deleteSiteSelect (syndicated) ; } else if (action. equalsIgnoreCase ("delbg" ) ) { outputHTML = deleteGroupSelect (jbsid, forwardLink, forwardPost, syndicated) ; E-2 } else if (action. equalsIgnoreCase ( "delbb" ) ) { outputHTML = viewGroupBlurbstjbsid, jbgid, jbbid, forwardLink, forwardPost, "Are you <B>sure</B> you want to delete the blurb shown?", syndicated); } else if (action. equalsIgnoreCase ( "viewbb") ) { outputHTML = viewBlurbSelect (jbsid, forwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase ("viewbbpostl") ) { outputHTML = viewGroupBlurbs (jbsid, bgid, -1, orwardLink, forwardPost, " ", syndicated) ; } else if (action. equalsIgnoreCase("delbgpostl") ) { outputHTML = deleteGroupDetails (jbsid, forwardLink, orwardPost, request, response, syndicated) ; } else if (action. equalsIgnoreCas ("delbgpost2") ) { outputHTML = doGroupDelete ( bsid, orwardLink, forwardPost,request,response, syndicated) ; } else if (action. equalsIgnoreCase ( "delbbpostl" ) ) { outputHTML = doBlurbDeletef bsid, bgid, jbbid, forwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase ( "delpostl" ) ) { outputHTML = deleteSiteDetails (request, response, syndicated); } else if (action. equalsIgnoreCase ("delpost 2 ") ) { outputHTML = doSiteDelete (request, response, syndicated); } else if (action. equalsIgnoreCase ("genbcode") ) { outputHTML = generateBlurbCode (jbsid, forwardLink, forwardPost, syndicated) ; } else if (action. equalsIgnoreCase ("viewbg") ) { outputHTML = viewGroups (jbsid, orwardLink, orwardPost, syndicated) ; } else if (action. equalsIgnoreCase) "genbcodepostl") ) { outputHTML = AdminMenuHTML.generateBlurbCode (jbsid, jbgid, forwardLink, this .serverRoot, getSiteNameFromld (jbsid) , getGroupNameFromld (jbgid) ) ; } } return outputHTML; } private synchronized String doSiteAdd (HttpServletRequest request, HttpServletResponse response, boolean syndicated) { boolean errFlag = false; int id = 0; int count = 1; double tempval ; Connection conn; Vector rs = null; BlurbSiteDB bs = new BlurbSiteDB { ) ; String blurb_site_name = request.getParameter ( "blurb_site_name") -trimf ) ; String description = request.getParameter ("description" ). trimf ) ; String url = request.getParameter ("url") . trimO ; /* Test if site, desc, and http:// are valid */ try { if (blurb_site_name.trim() .e ualsIgnoreCaseC") ) { return AdminMenuHTML. siteAddOrModify(this.serverRoot + this. thisServlet, -1, blurb_site_name, description, url, "An error occured. An invalid <B>Site Name or Site Description</B> was entered.") ; } if (description. trimO .equalsIgnoreCase( "") ) { return AdminMenuHTML.siteAddOrModify (this.serverRoot + this. thisServlet, -1, blurb_site_name, description, url, "An error occured. An invalid <B>Site Name or Site Description</B> was entered.") ,- } } catch (Exception e) { BlurbCommon.handleException(e) ; return AdminMenuHTML.siteAddOrModify (this. serverRoot + this. thisServlet, -1, blurb_site_name, description, url, "An error occured. An invalid <B>Site Name or Site Description</B> was entered.") ; } /* Test for a valid URL */ E-3 if (url . length ( ) > 9) { if (url. substring (0,7) .equalsIgnoreCase ("http://") ) { } else if (url. subs ring (0,8) .equalsIgnoreCase ( "https://") ) { ) else { return AdminMenuHTML. siteAddOrModify(this. serverRoot + this. thisServlet, -l,blurb_site_name, description,url, "An error occurred. An invalid <B>Site URL</B> was entered."),- } } else { return AdminMenuHTML. siteAddOrModify (this.serverRoot + this. thisServlet, -l,blurb_site_name, escription,url, "An error occurred. An invalid <B>Site URL</B> was entered."); } if ( !url. substring (0,5) .equalsIgnoreCase ("https") ) { try { URL testURL = new URL (url); } catch (Exception e) { BlurbCommon.handleException(e) ; return AdminMenuHTML. siteAddOrModify (this. serverRoot + this. thisServlet, -l,blurb_site_name,description,url, "An error occurred. An invalid <B>Site URL</B> was entered."); } } /* Pick a random id for blurb_site and make sure that a record with that id doesn't already exist. */ conn = dataConnMan.getConnection (server, dbname); while (count > 0) { te pval = Math, floor (1000000 * Math .random () ) ; id = (int) tempval ; try { rs = bs.getAll(conn, "blurb_site_id = " + id) ; ) catch (Exception e) { BlurbCommon.handleException(e) ; brea ; } count = rs.sized ; } dataConnMan.freeConnection (server, dbname, conn); if (count > 0) return AdminMenuHTML.getAdminMenu(getFirstSiteId() , this.serverRoot + this. hisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "An error occurred. The new site configuration was not added. ", syndicated) ; /* Make sure that blurb_site_jιame doesn' t already exist in the database . */ conn = dataConnMan.getConnection (server, dbname); try { //blurb_site_name = new RE ( " ' " ) . substituteAll (blurb_site_name, " ' " ) ; rs = bs .getAll f conn, "blurb_site_name = ' " + new RE( " ' " ) .substituteAll (blurb_site_name, » " » ) + " ' " ) ; } catch (Exception e) { BlurbCommon. handleException (e) ; errFlag = true; } dataConnMan . reeConnection (server, dbname, conn) ; if(rs.size() > 0) return AdminMenuHTML. siteAddOrModify(this. serverRoot + this. thisServlet, -l,blurb_site_name, escription,url, "The site <B>" + blurb_site_name + "</B> already exists. Please try again."); if (errFlag) return AdminMenuHTML.getAdminMenu(getFirstSiteldO , this . serverRoot + this.thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "An error occurred. The new site configuration was not adde .", syndicated) ; E-4 //attempt to do the database insert of the new blurb_site record; bs.blurb_site_id = id; bs.blurb_site_name = blurb_site_name; bs. escription = description; bs.url = url; bs. status = "Y"; bs.created_on = new Java.util.DateO ; bs.last_modified_on = new ava.util.DateO ; conn = dataConnMan.getConnection (server, dbname); try { bs .insert (conn) ; } catch (Exception e) { BlurbCommon. andleException(e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn); if (errFlag) return AdminMenuHTML.getAdminMenu (getFirstSiteldO , this. serverRoot + ■ this. thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "An error occurred. The new site configuration was not added. " (Syndicated) ; else return AdminMenuHTML.getAdminMenu (getFirstSiteldO , this . serverRoot + this.thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "The new site configuration for <B>" + blurb_site_name + "</B> was added successfully. " , syndicated) ; . } private synchronized String doGroupAd (HttpServletRequest request, HttpServletResponse response. String forwardLink, String forwardPost, boolean syndicated) { boolean errFlag = false; int id = 0; int count = 1; double tempval ; Connection conn; Vector rs = null; BlurbGroupDB bg = new BlurbGroupDB ( ) ; int jbsid = Integer.parselnt (request.getParameter ("jbsid" ) .trim() ) ; String blurb_group_na∞e = request .getParameter ("blurb_group_name") .trimO ; //String description = request.getParameter ( "description") . trimO ; if (blurb_group_name == null) { return AdminMenuHTML. groupAdd(jbsid, -1, forwardLink, forwardPost,blurb_group_name, getSiteSelectList ( bsid, false, syndicated) , "An Invalid blurb group name. Please try again."); } else if (blurb_group_name.trim() .equalsIgnoreCaseC") ) { return AdminMenuHTML.groupAdd(jbsid, -1, forwardLink, forwardPost,blurb_group_name, getSiteSelectList (jbsid, false, syndicated) , "An Invalid blurb group name. Please try again."); } /* Pick a random id for blurb_group and make sure that a record with that id doesn't already exist. */ conn = dataConnMan.getConnection (server, dbname) ; while (count > 0) { tempval = Math. floor (1000000 * Math . random ( ) ) ; id = (int) tempval; try { rs = bg.getAll (conn, "blurb_group_id = " + id) ; J catch (Exception e) { BlurbCommon. handleException (e) ; break; } count = rs . size O ; } dataConnMan. reeConnection (server, dbname, conn); if (count > 0) E-5 return AdminMenuHTML. getAdminMenu (jbsid, forwardLink, getSiteSelectList (getFirstSiteldO , true, syndicated) , "An error occurred. The new blurb group was not added. ", syndicated) ; /* Make sure that blurb_group_name doesn't already exist in the database. */ conn = dataConnMan.getConnection (server, dbname); try { rs = bg.getAll (conn, "blurb_group_name = '" + new RE(" '") .substituteAll (blurb_group_name, """) + "'"); } catch(Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection(server, dbname, conn); if(rs.size() > 0) return AdminMenuHTML. groupAdd(jbsid, -1, forwardLink, forwardPost,blurb_group_name, getSiteSelectList (jbsid, false, syndicated) , "The group <B>" + blurb_group_name + "</B> already exists. Please try again. " ) ; if (errFlag) return AdminMenuHTM .getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred. The new blurb group was not added. ", syndicated) ; //attempt to do the database insert of the new blurb_group record; bg.blurb_site_id = jbsid; bg.blurb_group_id = id; bg.blurb_group_name = blurb_group_name; //bg.description = description; bg.status = "Y"; bg.created_on = new Java.util.DateO ; bg.last_modified_on = new Java.util.DateO ; conn = dataConnMan.getConnection (server, dbname) ; try { bg . insert (conn) ; ) catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn) ; if (errFlag) return AdminMenuHTML. getAdminMenu(jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred. The new blurb group was not added. "(Syndicated) ; else return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "The new blurb group <B>" + blurb_group_name + "</B> was added to the <B>" + getSiteNameFromld!jbsid) + "</B> site. " syndicated) ; } private synchronized String doBlurbAdd(HttpServletRequest request, HttpServletResponse response. String forwardLink, String forwardPost, boolean syndicated) { boolean errFlag = false; int id = 0; int count = 1; double tempval,- Connection conn; Vector rs = null; BlurbDB bb = new BlurbDB ( ) ; GregorianCalendar gc = new GregorianCalendarO ; int jbsid = Integer,parselnt (request.getParameter ( "jbsid") .trimO ) ; int jbgid = Integer.parselnt (request.getParameter ("jbgid") .trimO ) ; String html = request.getParameter ( "html") . trim() ; E-6 /* Pick a random id for blurb and make sure that a record with that id doesn't already exist. */ conn = dataConnMan.getConnection (server, dbname) ,- while (count > 0) { tempval = Math. floo (1000000 * Math.random() ) ; id = (int) tempval; try { rs = bb.getAlKconn, "blurb_id = " + id); } catch (Exception e) { BlurbCommon.handleException (e) ; break; } count = rs.sizeO; } dataConnMan. freeConnection (server, dbname, conn) ; if (count > 0) return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred. The new blurb was not added. ", syndicated) ; //attempt to do the database insert of the new blurb record; bb.blurb_site_id = jbsid; bb.blurb_group_id = jbgid; bb.blurb_id = id; bb.html = html; bb.status = "Y" ; //bb.created_on = new java.util.Date () ; bb. created_on = new Timestam (gc.getTime () . getTime( ) ) ; bb.last_modified_on = new Timestamp (gc.getTime () -getTime ()) ; conn = dataConnMan.getConnection (server, dbname) ; try { bb. insert (conn) ; } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn); if (errFlag) return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectLis ( bsid, true, syndicated) , "An error occurred. The new blurb was not added. ", syndicated) ; else return viewGroupBlurbs( bsid, jbgid, -1, forwardLink, forwardPost, "The new blurb was added successfully. " , syndicated) ; } private String doSiteChange (HttpServletRequest request, HttpServletResponse response, boolean syndicated) { boolean errFlag = false; Connection conn; Vector rs = null; BlurbSiteDB bs = new BlurbSiteDB () ; int id = Integer. arselnt (request.getParameter! "jbsid") .trimO ) ; int tempid = id; String blurb_site_name = request.getParameter ( "blurb_site_name") .trimO ; String description = request.getParameter ( "description") -trim() ; String url = request. getParameter ("url") .trim() ; /* Test if site, desc, and http:// are valid */ try { if (blurb_site_name. tri () .equalsIgnoreCase ( " " ) ) { E-7 return AdminMenuHTML. siteAddOrModifyfthis. serverRoot + this. thisServlet, id, blurb_site_name, description, url, "An error occured. An invalid <B>Site Name or Site Description</B> was entered.") ; } if (description. trim() . equalsIgnoreCase ( " ") ) { return AdminMenuHTML.siteAddOrModify(this. serverRoot + this. thisServlet, id, blurb_site_name, description, url, "An error occured. An invalid <B>Site Name or Site Description</B> was entered.") ; } } catch(Exception e) { BlurbCommon.handleException (e) ; return AdminMenuHTML.siteAddOrModify(this.serverRoot + this. thisServlet, id, blurb_site_name, description, url, "An error occured. An invalid <B>Site Name or Site Description</B> was entered.") ; } /* Test for a valid URL */ if (url. length!) > 9) { if (url. substring(0,7) .equalsIgnoreCase("http://") ) { } else if (url. substring(0, 8) .equalsIgnoreCase! "https://") ) { } else { return AdminMenuHTML. siteAddOrModify(this. serverRoot + this. thisServlet, id, blurb_site_name, description,url, "An error occurred. An invalid <B>Site URL</B> was entered. "); } } else { return AdminMenuHTML. siteAddOrModify(this.serverRoot + this. thisServlet, id,blurb_site_name, description,url, "An error occurred. An invalid <B>Ξite URL</B> was entered."); } if ( ! rl. substring (0,5) . equalsIgnoreCase ( "https" ) ) { try { URL testURL = new URL (url) ; } catc (Exception e) { BlurbCommon.handleException (e) ; return AdminMenuHTML. siteAddOrModify(this. serverRoot + this.thisServlet, id, blurb_site_name, description,url, "An error occurred. An invalid <B>Site URL</B> was entered. "); } } /* Make sure that the new blurb_site_name doesn't already exist in the database. */ conn = dataConnMan.getConnection (server, dbname); try { //blurb_site_name = new RE(" ' ") . substituteAll (blurb_site_name, "''"); rs = bs.getAllfconn, "blurb_site_name = '" + new RE(" ' ") .substituteAll (blurb_site_name, " " " ) + " ' " ) ; } catch (Exception e) { BlurbCommon.handleExceptio (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn) ; if (errFlag) return AdminMenuHTML.getAdminMenu(getFirstSiteId() , this.serverRoot + this.thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "An error occurred. The site configuration change was not completed. ", syndicated) ; if(rs. sized > 0) { Enumeration e = rs.elements!) ; while (e.hasMoreElements ( ) ) { BlurbSiteDB record = (BlurbSiteDB) e.nextElementO ; tempid = record. lurb_site_id; } E-8 if (tempid != id) return AdminMenuHTML.siteAddOrModify(this. serverRoot + this. hisServlet, id,blurb_site_name, escription,url, "The site <B>" + blurb_site_name + "</B> already exists. Please try again. "); } //attempt to do the database update of the modified blurb_site record; bs.blurb_site_id = id; bs.blurb_site_name = blurb_site_name; bs. escription = description; bs.url = url; bs. status = "Y"; bs . created_on = new java.util.Date () ,- bs.last_modified_on = new ava.util.DateO ; conn = dataConnMan.getConnection (server, dbname); try { bs.update(conn) ; } catch (Exception e) { BlurbCommon.handleException (e) ,- errFlag = true; } d taConnMan.freeConnection (server, dbname, conn); if (errFlag) return AdminMenuHTML.getAdminMenu (getFirstSiteldO , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "An error occurred. The site configuration was not changed. ", syndicated) ; else return AdminMenuHTML.getAdminMenu (getFirstSiteldO , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "The site configuration for <B>" + blurb_site_name + "</B> was changed successfully. ", syndicated) ; } private String doBlurbChange (HttpServletRequest request, HttpServletResponse response, String forwardLink, String forwardPost, boolean syndicated) { boolean errFlag = false; Connection conn; Vector rs = null; BlurbDB bb = new BlurbDB () ; int jbsid = Integer.parselnt(request.getParameter {"jbsid") .trimO ) ; int jbgid = Integer,parselnt (request. getParameter ("jbgid") .trimO ) ; int id = Integer,parselnt (request.getParameter ( "jbbid") .trimO ) ; int tempid = id; String html = request.getParameter("html") -trimO ; //attempt to do the database update of the modified blurb record; bb.blurb_id = id; bb.blurb_group_id = jbgid; bb.blurb_site_id = jbsid; bb.ht l = html; bb. status = "Y" ; bb. created_on = new Java.util.Date () ; bb.last_modified_on = new Java.util.DateO ; conn = dataConnMan.getConnection(server, dbname) ; try { bb.update (conn) ; } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn) ; if (errFlag) return AdminMenuHTML.getAdminMenufjbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred. The blurb was not changed. ", syndicated) ; else E-9 //return AdminMenuHTML. getAdminMenu (jbsid, this.serverRoot + this. thisServlet, getSiteSelectLis (jbsid, true) , "The blurb was changed successfully."); return viewGroupBlurbs (jbsid, jbgid, -1, forwardLink, forwardPost, "The blurb was changed successfully. " , syndicated) ; } private String doSiteDelete (HttpServletRequest request, HttpServletResponse response, boolean syndicated) { boolean errFlag = false; Connection conn; Vector rg = null, rb = null; BlurbSiteDB bs = new BlurbSiteDB() ; BlurbDB bb = new BlurbDB () ; BlurbGroupDB bg = new BlurbGroupDB ( ) ; int id = Integer.parselnt (request.getParameter ("jbsid") .trim() ) ; //attempt to delete the blurb_site record and all associated blurb group and blurb records,- bs .blurb_site_id = id; conn = dataConnMan.getConnection (server, dbname); try { rb = bb.getAll (conn, "blurb_site_id=" + id) ; rg = bg.getAll (conn, "blurb_site_id= " + id) ,- if (rb.size ( ) > 0) { Enumeration q = rb. elements ( ) ; while (q.hasMoreElements O ) { BlurbDB b_record = (BlurbDB) q.nextElement ( ) ; b_record.delete (conn) ; } } if(rg.size() > 0) { Enumeration x = rg . elements () ; while (x.hasMoreElements () ) { BlurbGroupDB g_record = (BlurbGroupDB) x.nextElement () ; g_record.delete (conn) ; } } bs.delete(conn) ; } catch (Exception e) { BlurbCommon.handleException (e) ,- errFlag = true; } dataConnMan. freeConnection (server, dbname, conn) ; if (errFlag) return AdminMenuHTML.getAdminMenu (getFirstSitel () , this . serverRoot + this. thisServlet, getSiteSelectList(getFirstSiteId() , true, syndicated) , "An error occurred. The site configuration was not deleted. ", syndicated) ; else return AdminMenuHTML.getAdminMen (getFirstSiteld() , this.serverRoot + this . thisServlet, getSiteSelectList(getFirstSiteId() , true, syndicated) , "The site configuration was deleted successfully. " syndicated) ; } private String doGroupDelete(int jbsid. String forwardLink, String forwardPost, HttpServletRequest request, HttpServletResponse response, boolean syndicated) { boolean errFlag = false; Connection conn; Vector rb = null; BlurbDB bb = new BlurbDB ( ) ,- BlurbGroupDB bg = new BlurbGroupDB ( ) ; int id = Integer.parselnt (request.getParameter ("jbgid") .trim() ) ; //attempt to delete the blurb_group record and all associated blurb records; bg.blurb_group_id = id; conn = dataConnMan.getConnection (server, dbname) ; try { rb = bb.getAll (conn, "blurb_site_id=" + jbsid + " and blurb_group_id = " + id) ; if(rb.size() > 0) { E-10 Enumeration q = rb. elements 0 ,- while (q.hasMoreElements () ) { BlurbDB b_record = (BlurbDB) q.nextElement () ; b_record.delete(conn) ,- } } bg.delete (conn) ; } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. reeConnection (server, dbname, conn); if (errFlag) return AdminMenuHTML.getAdminMenu (jbsid, orwardLink, getSiteSelectList ( bsid, true, syndicated) , "An error occurred. The group was not deleted. ", syndicated) ; else return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "The group was deleted successfully. ", syndicated) ; } private String doBlurbDelete(int jbsid, int jbgid, int jbbid. String forwardLink, String forwardPost, boolean syndicated) { boolean errFlag = false Connection conn; Vector v = null; BlurbDB bb = new BlurbDB ( ) ,- //attempt to delete the blurb record bb.blurb_id = jbbid; conn = dataConnMan.getConnection(server, dbname) ,- try { bb. elete (conn) ; } catch (Exception e) { BlurbCommon. andleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn) ; if (errFlag) return AdminMenuHTML.getAdminMenu(jbsid, forwardLink, getSiteSelectListfjbsid, true, syndicated) , "An error occurred. The blurb was not deleted. " .syndicated) ; else return viewGroupBlurbs (jbsid, jbgid, -1, forwardLink, forwardPost, "The blurb was deleted successfully. " , syndicated) ; } //private String getSiteSelectList (int jbsid, boolean syndicated) { //return getSiteSelectList (jbsid, false, syndicated) ; //} private int getFirstSitel O { boolean errFlag = false; boolean first = true; int id = -1; BlurbSiteDB bs = new BlurbSiteDB () ; Vector v = null; Connection conn = dataConnMan.getConnection(server, dbname) ; try { v = bs.getAll (conn, "1=1 order by blurb_site_name asc"); } catc (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn); E-ll i (errFlag) return -1; Enumeration e = v.elements {) ; if(v.sizet) > 0) { while (e.hasMoreElements () ) { BlurbSiteDB record = (BlurbSiteDB) e.nextElement () ; if (first) id = record.blurb_site_id; first = false } } else { id = -1; } return id; } private String getSiteNameFromld(int jbsid) { boolean errFlag = false; String blurb_site_name = " " ; BlurbSiteDB bs = new BlurbSiteDB ( ) ; Vector v = null; Connection conn = dataConnMan.getConnection (server, dbname); try { v = bs.getAll (conn, "blurb_site_id .=" + jbsid) ,- } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnectionfserver, dbname, conn); if (errFlag) return "error"; Enumeration e = v.elements () ; if(v.size() > 0) { while (e.hasMoreElements () ) { BlurbSiteDB record = (BlurbSiteDB) e.nextElement () ; blurb_site_name = record.blurb_site_name; } } else { blurb_site_name = "error"; ) return blurb_site_name; } private String getGroupNameFromlddnt jbgid) { boolean errFlag = false; String blurb_group_name = " " ; BlurbGroupDB bg = new BlurbGroupDB ( ) ; Vector v = null ; Connection conn = dataConnMan.getConnection (server, dbname); try { v = bg.getAll (conn, "blurb_group_id =" + jbgid); } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnectio (server, dbname, conn); if (errFlag) return "er or" ; Enumeration e = v.elements () ; if(v.sizef) > 0) { while (e.hasMoreElements () ) { BlurbGroupDB record = (BlurbGroupDB) e.nextElement () ; blurb_group_name = record.blurb_group_name; ) E-12 } else { blurb_group_name = "error" ; } return blurb_group_name; } private String getBlurbHTMLFroml fint jbbid) { boolean errFlag = false,- String html = " " ; BlurbDB bb = new BlurbDB ( ) ; Vector v = null; Connection conn = dataConnMan. etConnection (server, dbname) ; try { v = bb.getAll (conn, "blurb_id =" + jbbid); } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. reeConnection (server, dbname, conn) ; if (errFlag) return "erro " ; Enumeration e = v. elements () ; if(v.size() > 0) { while (e.hasMoreElements) ) ) { BlurbDB record = (BlurbDB) e.nextElement () ; html = record.html; } } else { html = "error" ; } return html; } private String getSiteSelectList (int jbsid, boolean includeJavascript, boolean syndicated) { boolean errFlag = false,- boolean first = true; BlurbSiteDB bs = new BlurbSiteDB () ; Vector v = null; i (syndicated) return getSiteNameFromld(jbsid) ; else { Connection conn = dataConnMan.getConnection (server, dbname) ; try { v = bs.getAll (conn, "1=1 order by blurb_site_name asc"); } catch(Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. reeConnection (server, dbname, conn); if (errFlag) return "error" ; Enumeration e = . elements () ; StringBu fer sb = new StringBuffer ( ) ; StringBuffer jparams = new StringBufferO ; StringBuffer js = new StringBu ferO; if (v. size( ) > 0) { if (includeJavascript) sb. append ( "<SELECT NAME=\ " bsid\" onChange=\ " go (this , 1 , false) \ ">" + ' \r' ) ; else sb. append ( "<SELECT NAME=\ " bsid\">" + ' \r' ) ; while (e.hasMoreElements ( ) ) { BlurbSiteDB record = (BlurbSiteDB) e.nextElement ( ) ; if (first) j Par ams . appen ( " \ " \ " , \ " " + this . serverRoot + this . thisServlet + "?jbsid=" + E-13 record.blurb_site_id + "\""); else j arams.append (",\"" + this.serverRoot + this. thisServlet + "?jbsid=" + record.blurb_site_id + "\""); i ((first) && (includeJavascript) ) sb.append("<option value=\"\">Select a site »</option>" + '\r'); i (jbsid == record.blurb_site_id) sb. append("-option value=\"° + record.blurb_site_id + "\" selected>" + record.blurb_site_name + "</option>" + '\r'); else sb.append( "<option value=\"" + record.blurb_site_id + » \">" + record.blurb_site_name + "</option>" + '\r'); first = false; } sb.append ("</SELECT>" + '\r'); if (includeJavascript) { String redirParams = Params. toString () ; js. append ( "<SCRIPT language=\"JavaΞcriptl.2\">" + '\r'); js. append( "function buildArray!) {" + '\r'); js. append( "var a = buildArray.arguments; " + '\r'); js.appendf "for (i=0; i<a. length; i++) {" + '\r'); js.append) "this[i] = a[i];" + '\r'); js. append ( "} " + '\r'); js. append ( "this. length = a. length;" + '\r'); js. appen ( "} " + '\r'); js.append ( "var urlsl = new buildArray(" + redirParams + "),-" + '\r'),- // System. out .println (redirParams) ; js. append ( "function jgo(which, num, win) {" + '\r'); js.append("n = which. selectedlndex; " + '\r'); js.appendO'if (n != 0) {" + '\r'); s. append ( "var url = eval (\ "urls\" + num + \"[n]\")" + '\r'); js. append) "if (win) {" + '\r'); js.append( "openWindow(url) ; " + '\r'); js.append(") else {" + '\r'); js. append) "location.href = url;" + '\r'); js. append ( "} " + '\r'); js. append! "}" + '\r'); js. append) "} " + '\r'),- s. append ("</SCRIPT>" + '\r'); ) } else { return "none"; } return js. toString)) + sb. toStrin 0 ; } } private String getGroupSelectList (int jbsid, int jbgid) { boolean errFlag = false; boolean first = true; BlurbGroupDB bg *= new BlurbGroupDB() ; Vector v = null; Connection conn = dataConnMan.getConnection (server, dbname) ; try { v = bg.getAll (conn, "blurb_site_id = " + jbsid + " order by blurb_group_name asc"); } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true,- } dataConnMan. freeConnection (server, dbname, conn); if (errFlag) return "error" ; Enumeration e = v. elements () ; StringBuffer sb = new StringBu fe ( ) ; E-14 if (v. size ( ) > 0) { sb.appen ("<SELECT NAME=\"jbgid\">" + '\r'); while (e.hasMoreElements!)) { BlurbGroupDB record = (BlurbGroupDB) e.nextElement O ; //i (first) //sb.append! "<option value=\"\">Select a site »</option>" + '\r'); if (jbgid == record.blurb_group_id) sb.append ( "<option value=\"" + record.blurb_group_id + "\" selected>" + record.blurb_group_name + "</option>" + '\r'); else sb. append! "<option value=\"" + record.blurb_group_id + "\">" + record.blurb_group_name + "</option>" + '\r'); first = false; } sb. append ("</SELECT>" + '\r'); } else { return "none"; } return sb. toString ( ) ,- } private String viewGroups (int jbsid, String forwardLink, String forwardPost, boolean syndicated) { boolean errFlag = false; BlurbGroupDB bg = new BlurbGroupDB ( ) ; BlurbDB bb = new BlurbDB( ) ; Vector v = null, z = null; Connection conn = dataConnMan.getConnection (server, dbname) ; try { v = bg.getAll (conn, "blurb_site_id = " + jbsid + " order by blurb_group_name asc"); } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn) ; Enumeration e = v. elements () ; StringBuffer sb = new StringBufferO; if(v.size() > 0) { conn = dataConnMan. getConnection (server, dbname) ,- while (e.hasMoreElements))) { BlurbGroupDB record = (BlurbGroupDB) e.nextElement)); try { z = bb.getAll (conn, "blurb_site_id = " + jbsid + " and blurb_group_id = " + record.blurb_group_id) ; sb. append { "<trxtd align=left>S;nbsp;&nbsp;r-nbsp; " + record.blurb_group_name + "</tdxtd align=left>&nbsp;&nbsp;S:nbsp; " + z.sizeO + "</tdx/tr>" + '\r'); } catch (Exception ex) { BlurbCommon.handleException (ex) ; errFlag = true; } } dataConnMan. reeConnection (server, dbname, conn) ; } else { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink,getSiteSelectList (jbsid, true, syndicated) , "No groups are currently configured. Please add a new group. ", syndicated) ; } i (errFlag) return AdminMenuHTML.getAdminMenu (jbsid, orwardLink,getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database .", syndicated) ; else return AdminMenuHTML.viewGroups (jbsid, forwardLink, forwardPost, sb. toString)) .getSiteNameFromld(jbsid) ) ; } private String changeSiteDetails (HttpServletRequest request, HttpServletResponse response, boolean syndicated) { E-15 boolean errFlag = false; int id = Integer.parseln (request. getParameter ("jbsid") .trim() ) ; String blurb_site_name = ""; String description = " " ; String url = " " ; Vector rs = null; BlurbSiteDB bs = new BlurbSiteDB () ; Connection conn = dataConnMan.getConnection (server, dbname) ; try { rs = bs.getAll (conn, "blurb_site_id = " + id); } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnectio (server, dbname, conn) ; if (errFlag) return AdminMenuHTML.getAdminMenu(getFirstSiteld!) , this . serverRoot + this.thisServlet, getSiteSelectList (getFirstSiteld!) , true, syndicated) , "An error occurred in connecting to the database. " , syndicated) ; if(rs.size() > 0) { Enumeration e = rs . elements ( ) ,- while (e.hasMoreElements!)) { BlurbSiteDB record = (BlurbSiteDB) e.nextElement!); blurb_site_name = record.blurb_site_name; description = record.description; url = record.url,- } } else { return AdminMenuHTML.getAdminMenu (getFirstSiteld!) , this. serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "The site record selected no longer exists in the database. ", syndicated) ,- } return AdminMenuHTML. siteAddOrModify (this. serverRoot + this. thisServlet, id,blurb_site_name, escription, url, " " ) ; } private String changeSiteΞelect (boolean syndicated) { String param = getSiteSelectLis (-1, false, syndicated) ; if (param. equals ( "error") ) { return AdminMenuHTML.getAdminMen (getFirstSiteld) ) , this. serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteld) ), true, syndicated) , "An error occurred in connecting to the database. " , syndicated) ,- } else if (param. equals ("none") ) { return AdminMenuHTML.getAdminMenu (getFirstSiteldO , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteldO , rue, syndicated) , "No sites are currently configured. Please configure a new site. ", syndicated) ,- } else { return AdminMenuHTML. selectsite(this. serverRoot + this. thisServlet, "chg", aram) ; } } private String genSiteCodeSelect (boolean syndicated) { String param = getSiteSelectList (-1, false, syndicated) ; if (param.equals ( "error") ) { return AdminMenuHTML.getAdminMenu (getFirstSitel O , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteldO , true, syndicated) , "An error occurred in connecting to the database. " , syndicated) ; } else if (param. equals ("none") ) { return AdminMenuHTML.getAdminMenu (getFirstSitel O , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteld) ), true, syndicated) , "No sites are currently configured. Please configure a new site. ", syndicated) ; } else { return AdminMenuHTML.selectsite(this. serverRoot + this. thisServlet, "gensitecode",param) ; } } /* private String changeGroupΞelect (boolean syndicated) { String param = getSiteSelectList (-1, false, syndicated); E-16 if (param. equals ( "error" ) ) { return AdminMenuHTML.getAdminMenu (getFirstSitel O , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSitel ( ), true, syndicated) , "An error occurred in connecting to the database . " , syndicated) ; } else if (param. equals ( "none" ) ) { return AdminMenuHTML.getAdminMenu (getFirstSiteldO , this.serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteld ( ), true, syndicated) , "No sites are currently configured. Please configure a new site. " .syndicated) ,- } else { return AdminMenuHTML. selectSite(this. serverRoot + this .thisServlet, "chg" ,param) ; } } */ private String deleteSiteSelect (boolean syndicated) { String param = getSiteSelectList (-1, false, syndicated) ; if (param. equals ( "error") ) { return AdminMenuHTML. getAdminMenu (getFirstSiteld)) , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteld)) , true, syndicated) , "An error occurred in connecting to the database. " , syndicated) ; } else if (param. equals ( "none" ) ) { return AdminMenuHTML.getAdminMenu (getFirstSitel () , this . serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteldO , true,syndicated) , "No sites are currently configured. Please configure a new site. ".syndicated) ; ) else { return AdminMenuHTML. selectsite(this. serverRoot + this. thisServlet, "del" .param) ; } } private String addBlurbfint jbsid. String forwardLink, String forwardPost, boolean syndicated) { String param = getGroupSelectLis (jbsid, -1); if (param. equals ( "error") ) { return AdminMenuHTM . getAdminMenu ( bsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database. ", syndicated) ; } else if (param. equals ( "none" ) ) { return AdminMenuHTML.getAdminMen (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "No blurb groups exist for the current site. <BR>Please add a new blurb group before adding a blurb. " , syndicated) ; } else { return AdminMenuHTML.blurbAddOrModify(jbsid, -1,-1, forwardLink, forwardPost, getSiteNameFromld (jbsid) , " " ,pa ram, " " ) ; } } private String copyBlurb(int jbsid, int jbgid, int jbbid. String forwardLink, String forwardPost, boolean syndicated) { String param = getGroupSelectList (jbsid, jbgid); String html = getBlurbHTMLFroml (jbbid) j; if (param. equals ("error") ) { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database. ", syndicated) ; } else if (param. equals ("none")) { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "No blurb groups exist for the current site. <BR>Please add a new blurb group before adding a blurb. " , syndicated) ; } else { return AdminMenuHTML.blurbAddOrModifyljbsid, jbgid, -1, forwardLink, forwardPost, getSiteNameFromld(jbsid) ,ht ml,param, "" ) ; } } private String changeBlurb(int jbsid, int jbgid, int jbbid. String forwardLink, String forwardPost, boolean syndicated) { String param = getGroupSelectList!jbsid, jbgid); E-17 String html = getBlurbHTMLFromld (jbbid) ; if (param. equals ( "error") ) { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database. ", syndicated) ,- } else if (param. equals ( "none" ) ) { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "No blurb groups exist for the current site. <BR> lease add a new blurb group before adding a blurb. " , syndicated) ; } else { return AdminMenuHTML .blurbAddOrModify (jbsid, jbgid, jbbid, forwardLink, forwardPost, getSiteNameFromld(jbsid) .html,param, " " ) ; } } private String deleteGroupSelect (int jbsid, String forwardLink, String forwardPost, boolean syndicated) { String param = getGroupSelectList (jbsid, -1) ; if (param.equals ( "error") ) { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink,getSiteSelectList (jbsid, truesyndicated) , "An error occurred in connecting to the database. ", syndicated) ,- } else if (param.equals ( "none") ) { return AdminMenuHTML.getAdminMenu ( bsid, orwardLink, getSiteSelectList (jbsid, true, syndicated) , "No groups are currently configured. Please add a new group .", syndicated) ; } else { return AdminMenuHTML. selectGrouptjbsid, forwardLink, forwardPost, "delbg" , param, getSiteNameFromld (jbsid) ) ,- } } private String viewBlurbSelect (int jbsid, String forwardLink, String forwardPost, boolean syndicated) { String param = getGroupSelectList (jbsid, -1) ,- if (param. equals ( "error") ) { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database . " , syndicated) ,- } else if (param. equals ( "none") ) { return AdminMenuHTML.getAdminMenu (jbsid, orwardLink, getSiteSelectList (jbsid, true, syndicated) , "No groups are currently configured. Please add a new group. " .syndicated) ,- } else { return AdminMenuHTML.selectGroup) bsid, forwardLink, forwardPost, "viewbb" , param, getSiteNameFromld (jbsid) ) ; } } private String viewGroupBlurbs (int jbsid, int jbgid, int jbbid, String forwardLink, String forwardPost, String message, boolean syndicated) { boolean errFlag = false; BlurbDB bb = new BlurbDB ( ) ; Vector v = null ,- Connection conn = dataConnMan. getConnection (server, dbname); String q = " ? " ; if (forwardLink. indexOf ("?") > -1) q = "&" ; try { if (jbbid > 0) v = bb.getAll (conn, "blurb_site_id = " + jbsid + " and blurb_group_id = * + jbgid + " and blurb_id = " + jbbid + " order by created_on desc"),- else v = bb.getAll (conn, "blurb_site_id = * + jbsid + " and blurb_group_id = " + jbgid + " order by created_on desc" ) ; } catch (Exception ex) { BlurbCommon.handleException (ex) ; E-18 errFlag = true; } dataConnMan. freeConnection (server, dbname, conn); Enumeration e = v. elements () ,- StringBuffer sb = new StringBufferO; if(v.size() > 0) { conn = dataConnMan.getConnection (server, dbname) ,- while (e.hasMoreElements () ) { BlurbDB record = (BlurbDB) e.nextElement () ,- if (jbbid > 0) { sb.append) "<trxtd valign=top align=center>N/A</td>" ) ; } else { sb. append ( "<trxtd valign=top align=center>[<A HREF=\"" + forwardLink + q + "jbact=copybb&jbsid=" + jbsid + "&jbgid=" + jbgid + "&jbbid=" + record.blurb_id + "\"><B>Copy</Bx/A>]<BR>") ; sb.appen (" [<A HREF=\"" + forwardLink + q + "jbact=chgbb&jbsid=" + jbsid + "&jbgid=" + jbgid + "&jbbid=" + record.blurb_id + "\"><B>Modify</Bx/A>)<BR>") ,- sb. append (" [<A HREF=\"" + forwardLink + q + "jbact=delbb&jbsid=" + jbsid + "&jbgid=" + jbgid + "&jbbid=" + record.blurb_id + "\ "><B>Delete</Bx/A>I</td>" ) ; } sb.append( "<td valign=top align=left>" + HTMLQuoter. toQuoted(record,html) + "</tdxtd valign=top align=left>" + record.html + "</tdx/tr>" + '\r'),- } dataConnMan. freeConnection (server, dbname, conn); > else { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "The group <B>" + getGroupNameFroml (jbgid) + "</B> doesn't contain any HTML blurbs. ", syndicated) ; } if (errFlag) return AdminMenuHTML. getAdminMenu (jbsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database. ", syndicated) ; else ifijbbid > 0) return AdminMenuHTML . eleteBlurb(jbsid, jbgid, jbbid, forwardLink, orwardPost , s . toString ( ) , getSiteNameFrom Id(jbsid) .getGroupNameFromld)jbgid) , message) ; else return AdminMenuHTML.viewGroupBlurbs (jbsid, jbgid, forwardLink, forwardPost, sb. toString () .getSiteNameFromld (jbsid) .getGroupNameFromld (jbgid) , message) ; } private String generateBlurbCode ( int jbsid. String forwardLink, String forwardPost, boolean syndicated) { String param = getGroupSelectList (jbsid, -1) ,- if (param. quals ( "error" ) ) { return AdminMenuHTML . getAdminMenu ( bsid, forwardLink, getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database. ", syndicated) ; } else if (param. equals ( "none") ) { return AdminMenuHTML.getAdminMenu (jbsid, forwardLink,getSiteSelectList (jbsid, true, syndicated) , "No groups are currently configured. please add a new group. " .syndicated) ; } else { return AdminMenuHTML. selectGroup( bsid, forwardLink, forwardPost, "genbcode" .param, getSiteNameFromld!jbsid) ) ; } } private String deleteSiteDetails (HttpServletRequest request, HttpServletResponse response, boolean syndicated) { boolean errFlag = false; int id = Integer,parselnt (request.getParameter ("jbsid") .trimO ) ; String blurb_site_name = " " ; String description = " " ; String url = " " ; E-19 Vector rs = null; BlurbSiteDB bs = new BlurbSiteDB () ; Connection conn = dataConnMan.getConnection (server, dbname); try { rs = bs.getAlKconn, "blurb_site_id = " + id) ,- } catc (Exception e) { BlurbCommon.handleException(e) ; errFlag = true; } dataConnMan. reeConnection (server, dbname, conn); i (errFlag) return AdminMenuHTML. getAdminMenu (getFirstSiteldO , this. serverRoot + this. thisServlet, getSiteSelectList (getFirstSiteldO .true, syndicated) , "An error occurred in connecting to the database. " , syndicated) ; if(rs.size() > 0) { Enumeration e = rs.elements () ,- while (e.hasMoreElements () ) { BlurbSiteDB record = (BlurbSiteDB) e.nextElement () ; blurb_site_name = record.blurb_site_name; description = record. description; url = record.url; } } else { return AdminMenuHTML.getAdminMenu (getFirstSiteldO , this. serverRoot + this. thisServlet, getSiteSelectLis (getFirstSiteldO , true, syndicated) , "The site record selected no longer exists in the database. ", syndicated) ; } return AdminMenuHTML.siteDelete(this.serverRoot + this. thisServlet, id,blurb_site_name, description,url, "") ; } private String deleteGroupDetails (int jbsid, String forwardLink, String forwardPost, HttpServletRequest request, HttpServletResponse response, boolean syndicated) { boolean errFlag = false; int id = Integer.parselnt (request. getParameter ("jbgid" ). trimO ) ,- String blurb_group_name = " " ; Vector rs = null; BlurbGroupDB bg = new BlurbGroupDB ( ) ; Connection conn = dataConnMan.getConnection (server, dbname) ; try { rs = bg.getAlKconn, "blurb_group_id = " + id) ,- } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMa . reeConnection (server, dbname, conn); if (errFlag) return AdminMenuHTML. etAdminMenu (jbsid, orwardLink,getSiteSelectList (jbsid, true, syndicated) , "An error occurred in connecting to the database . " , syndicated) ; if(rs.size() > 0) { Enumeration e = rs . elements ( ) ; while (e.hasMoreElements () ) { BlurbGroupDB record = (BlurbGroupDB) e .nextEle ent () ; blurb_group_name = record.blurb_group_name; } } else { return AdminMenuHTML.getAdminMenu(jbsid, forwardLink,getSiteSelectList!jbsid, true, syndicated) , "The group record selected no longer exists in the database. ".syndicated) ; } return AdminMenuHTML. roupDelete)jbsid, id, forwardLink, forwardPost,blurb_group_name, " " , getSiteNameFroml ( jbsid) ) ; } E-20 private void validateSiteO { } E-21 //a test comment package com.activedatax. roducts .Blurb; import javax. servlet. *,- import java . servlet .http. * ; import java.io. * ,- import Java.util. *,- import Java. sql. *; import Java.net. * ; import gnu.regexp . * ; import com.activedatax. sql.HttpServletDb; import com. activedata .products .Blurb.dbmodules .BlurbDB; /* * This is a rewrite of the PublishNow 2.x jSyndicate servlet for use with Active Data Publisher 3 .0 and Community Exchange (AffiliateNow) Sauthor John E. Wetzel Θversion 1.0 Θdate 15-MAY-2000 */ public class JBlurb extends HttpServletDb implements SingleThreadModel { private BlurbCommon mycommon; private String server = " " ; private String dbname = " " ; private String thisServlet = " " ; private String serverRoot = " " ; public void init (ServletConfig config) throws ServletException { super . ini (con ig) ; //USE BlurbCommon . class TO GET PROPERTIES — SERVER & DATABASE NAME mycommon = new BlurbCommon ( ) ; Properties p = mycommon. getProps () ; serverRoot = p. getProperty ("server.root") ; server = p. getProperty ( "default. server" ) ; dbname = p. getProperty ( "default.dbname" ) ; //store the alias in p = mycommon. getAliases () ; thisServlet = p. getProperty("JBlurb" ) ,- } //Process the HTTP Get request public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String outputHTML = " " ; String param = " " ; String action = request.getParameter ("jbact") ; outputHTML = convertTojs(getRandomBlurb(Integer,parselnt (request.getParameter ( "jbsid" ) .trim() ) , Integer.parselnt (request.getParameter ("jbgid") .trimO) )) ; response.setContentType ( "text/html") ; PrintWriter out = response.getWriter () ; out.println (outputHTML) ; return; ' } public String getRandomBlurb(int blurb_site_id, int blurb_group_id) { boolean errFlag = false; int count = 0; int tempid, blurb_id; double tempval; String blurbHTML = " " , tempStr = " " ,- E-22 BlurbDB bb = new BlurbDB ( ) ,- Vector rs = null; Hashtable idHash = new Hashtable!) ,- Connection conn = dataConnMan.getConnection (server, dbname) ; String sql = "select blurb.blurb_id id from blurb_site, blurb_group, blurb " + " where upper (blurb_site. status) = 'Y' and upper (blurb_group.status) = 'Y' and upper (blurb. status) = » γ » " + " and blurb.blurb_site_id = blurb_group.blurb_site_id and blurb.blurb_site_id = blurb_site .blurb_site_id" + " and blurb.blurb_group_id = blurb_group.blurb_group_id" + " and blurb.blurb_site_id = ? and blurb.blurb_group_id = ?"; try { PreparedStatement stmt = conn.prepareStatement (sql) ; stmt .clearParameters ( ) ; stmt. setlnt (1, blurb_site_id) ; stmt . setlnt ( 2 , blurb_group_id) ; ResultSet rr = stmt.executeQuer ,- while (rr.nextO) { count++; idHash.put (String.valueOf (count) , rr .getStringO'id") ) ; } rr.close () ; stmt.close () ; } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn); i (count > 0) { tempval = Math. floor (count * Math.random()) ; tempid = (int) tempval + 1 ; // System. out -println (tempid) ,- tempStr = idHash.get (String. alueOf (tempid) ) .toStringO ,- blurb_id = Integer.parselnt (tempStr) ; // System.out .println (blurb_id) ; conn = dataConnMan. getConnection (server, dbname) ; try { rs = bb.getAll (conn, "blurb_id =" + blurb_id) ; } catch(Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn) ; Enumeration e = rs.elements () ; while (e.hasMoreElements () ) { BlurbDB record = (BlurbDB) e.nextElement () ; blurbHTML = record.getHtml () ; } } if (errFlag) return "<! database error >"; else return blurbHTML; public String convertTojs (String HTMLtext) { try { HTMLtext = new E-23 RE("\"com.activedatax.products.Affiliate.Datamodules.Retrievelmage") .substituteAll (HTMLtext, "V" + serverRoot + "com.activedatax.products.Affiliate.Datamodules.Retrievelmage") ; HTMLtext = new RE( » [Ss] [Rr] [Cc] *= *\ "com.activedatax.products.Affiliate.Datamodules.Retrievelmage") .substituteAll (HTMLtext, "src=\" ' + serverRoot + "com.activedatax.products.Affiliate.Datamodules.Retrievelmage") ; HTMLtext = new RE( " [Ss] [Rr] [Cc] *= *\"com.rnci.products.DataModules.Retrievelmage") .substituteAll (HTMLtext, "src=\" " + serverRoot + "com.rnci .products .DataModules .Retrievelmage" ) ,- HTMLtext = new RE("\"com.rnci.products.DataModules. etrieveAttachment") .substituteAll (HTMLtext, "\"" + serverRoot + "com. rnci.products.DataModules.RetrieveAttachment") ; } catch(Exception e) { BlurbCommon.handleException (e) ; ) String scriptHTML = " " ; int startSearchAt = 0; int scriptLoc = indexOfIgnoreCase (HTMLtext, "<SCRIPT" , startSearchAt) ; if (scriptLoc > -1) { //Check for client scripts and separate them from regular HTML try { int endScriptLoc; int articleLength = HTMLtext . length ( ) ; StringBuffer sbArticle = new StringBuffer(articleLength + 1) ,- StringBuffer sbScripts = new StringBuffer ( ) ; while (scriptLoc > -1) { endScriptLoc = indexOfIgnoreCase (HTMLtext, "</SCRIPT>" .scriptLoc) ; sbArticle. append(HTMLtext. substring(startSearchAt, scriptLoc) ) ; sbScripts.appen (HTMLtext. substring ( (indexOfIgnoreCase (HTMLtext, ">" .scriptLoc) +1) .endScriptLoc) ) ; sbScripts . append ( ' \n' ) ; sbScripts . appen ( ' \r' ) ; //System. out .println ("The HTML: " + HTMLtext. substring (startSearchAt, scriptLoc) ) ; //System. out.println ("The Script: " + HTMLtext.substring ( (indexOfIgnoreCase (HTMLtext, ">" , scriptLoc) +1) , endScriptLoc) ) ; startSearchAt = endScriptLoc + 9; scriptLoc = indexOfIgnoreCase (HTMLtext, "<SCRIPT", startSearchAt) ,- } sbArticle. append(HTMLtext.substring(startSearchAt, articleLength - 1)) ; //System. out.println (sbArticle. toStringO ) ; //System.out.printIn (sbScripts.toString() ) ; scriptHTML = sbScripts . toString ( ) , //contains just the scripts' code HTMLtext = sbArticle . toString ( ) ,- //contains just the article HTML } catch(Exception e) { BlurbCommon.handleException (e) ; } } HTMLtext = HTMLtext.replace ( '\r' , ' '); " HTMLtext = HTMLtext. eplace('\n' , ' ' ) ; try { HTMLtext = swapStrings (HTMLtext, "\\", "\\\\") HTMLtext = swapStrings (HTMLtext, "\' ,"\W") HTMLtext = swapStrings (HTMLtext, "\" ", "\\\" °) } catch(Exception e) { BlurbCommon.handleException (e) ; } return scriptHTML + " document.write (' + HTMLtext + '); } public static String swapStrings (String Textln, String OldString, String NewString) { int OldStringStartAt; int OldStringLength = OldString. length() ; int NewStringLength = NewString.length() ; E-24 String TempText = Textln; OldStringStartAt = indexOfIgnoreCase(TempText, OldString, 0) ; while (OldStringStartAt != -1) { TempText = TempText. substring ( 0, OldStringStartAt) + NewString + TempText. substring (OldStringStartAt + OldStringLength) ; OldStringStartAt = indexOfIgnoreCase (TempText, OldString, OldStringStartAt + NewStringLength) ; } return TempText; } public static int indexOfIgnoreCase (String TempText, String substring, int StartAt) return TempText. toLowerCase ().indexOf ( substring. toLowerCase () , StartAt); } E-25 //A simple comment package com.activedatax. roducts.Blurb; import javax. servlet .* ; import javax. servlet.http. *,- import java. io. * ; import Java.util.*; import java.sql . *; import com.activedata .products .Blurb. *; import com.activedatax .products .Blurb.dbmodules . * ; import gnu .regexp. * ; import com. activedatax.net .url .Util; import jav .net .MalformedURLException; import com.activedatax.utils -HTMLQuoter; public class JBlurbAdmin extends AdminMenu { private BlurbCommon mycommon; private String server = " " ; private String dbname = " " ; private String thisServlet = " " ; private String serverRoot = " " ; private String fPost = " " ; private static int itemsToKeep = 00, minutesToLive = 10; //will be set by init() later private static long lastModified; private static Vector contents = new Vector(); private Sentinel sentinel = null ; public void ini (ServletConfig config) throws ServletException { super. init (config) ; System. out.println ( "Init Method executed"),- sentinel = new Sentinel (itemsToKeep, minutesToLive); //USE BlurbCommon. class TO GET PROPERTIES mycommon = new BlurbCommon ( ) ; Properties p = mycommon. getProps () ; serverRoot = p.getProperty("server.root") ; server = p.getProperty ( "default. server" ) ; dbname = p.getProperty ( "default. dbname" ) ; try { this. itemsToKeep = Integer.parselnt (p.getProperty("cache. items") ) ; } catch (NumberFormatException e) { System. err.println(e.getMessage() ) ; e .printStackTrace ( ) ,- this.itemsToKeep = 400; } try { this.minutesToLive = Integer.parselnt (p.getProperty( "cache.minutes") ) ; } catch (NumberFormatException e) { System.err.println (e.getMessagef) ) ; e.printStackTrace)) ; this.minutesToLive = 10; } //store the alias in p = mycommon.getAliases () ; thisServlet = p. getProperty)" BlurbAdmin" ) ,- fPost = serverRoot + thisServlet,- } /**Process the HTTP Get request*/ public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String outputHTML = "", documentURL = "", documentHost = "", jbact = "", jpostbact = "", jbts = " " ; E-26 String contld; boolean errFlag = false; int jbsid = -1; Content cont; response. setContentType ( "text/html" ) ; PrintWriter out = response.getWri e () ; HttpSession session = request.getSession (false) ; if (session == null) session = request.getSessio (true) ; documentURL = removeAllParams (request. getParameter ("jbdurl") .trimO ) ,- //get the blurb site id from the request parameters try { jbsid = Integer.parselnt (request.getParameter ( "jbsid") .trimO ) ; } catch (Exception e) { errFlag = true; } if(lerrFlag) errFlag = validateHost (jbsid,parseHostFromURL (documentURL) ) ; if (errFlag) outputHTML = "document.write ( '<B>This web site is not authorized to view the content requested.<\\/B>') ; "; else { jbact = request.getParameter ("jbact") ; if (jbact != null) { if (jbact. equalsIgnoreCase ("getpostdata") ) { jbts = request.getParameter ("jbts") .trimO ; jpostbact = request.getParameter ("jpostbact") .trimO ; contld = session.getldO + "," + jbsid + "," + documentURL + "," + jpostbact + "," + jbts; //System.out.println(contld) ; cont = lookup (contld) ; if (cont != null) outputHTML = cont.detail ,- else outputHTML = convertTojs (doBlurb(request, response, documentURL, this.fPost, true)) out.println (outputHTML) ; return; } } outputHTML = convertTojs (doBlurb (request, response, documentURL, this.fPost, true)); } out.println (outputHTML) ,- return; } /**Prσcess the HTTP Post request*/ public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String outputHTML = "", referringURL = "", redirectURL = "", jpostbact = "", g = "?"; String contld; boolean errFlag = false; int jbsid = -1; Content cont; HttpSession session = request.getSession (false) ; if (session == null) session = request.getSession (true) ; //get the referring URL from the request header and use as the forward link referringURL = removeAllParams (request.getHeader ("REFERER") ) ; if (referringURL. equals ( "error" ) ) errFlag = true; //get the blurb site id and the form post action from the request parameters try { jbsid = Integer,parselnt (request.getParameter ("jbsid") .trimO ) ; jpostbact = request.getParameter ("jbact" .trim() ) ; } catch(Exception e) { errFlag = true; } i (errFlag == false) errFlag = validateHost (jbsid, arseHostFromURL (referringURL) ) ; i (! errFlag) { //process the posted form and convert to JS for output E-27 outputHTML = convertTojs (doBlurb(request, response, referringURL, this.fPost, true)); //store the resulting JS in a Vector for later retrieval via browser JavaScript HTTP GET if (referringURL. indexOf ("?") > -1) q = "&"; lastModified = System. currentTimeMillis () ,- redirectURL = referringURL + q + "jbsid=" + jbsid + "&jbact=getpostdata&jpostbact=" + jpostbact + "&jbts=" + lastModified; contld == session.getldO + " , " + jbsid + "," + referringURL + "," + jpostbact + "," + lastModified //Ξystem.out.println(contld) ; cont = new Content (contld, outputHTML, lastModified); contents . addElement (cont) ; } else { //there has been an error or the referring URL is not allowed redirectURL = referringURL; } //redirect the browser to the referring page with the appropriate parameters needed to retrieve the JS from the Vector response.sendRedirect (redirectURL) ; return; } /**Clean up resources*/ public void destroy!) { System. out.println! "Destroy method running" ); sentinel. uit = true; contents = null; } public String convertTojs (String HTMLtext) { try { HTMLtext = new RE ( " \ "com. activedatax.products .Af iliate -Datamodules .Retrievelmage" ) . substituteAll (HTMLtext, "V" + serverRoot + "com. activedatax.products.Affiliate.Datamodules.Retrievelmage") ; HTMLtext = new RE( " [Ss] [Rr] [Cc] *= *\ "com.activedatax.products.A filiate.Data odules.Retrievelmage") .substituteAll (HTMLtext, "src=\" + serverRoot + "com. activedatax.products.Affiliate.Datamodules.Retrievelmage") ; HTMLtext = new RE( " [Ss] [Rr] [Cc] *= *\"com.rnci.products.DataModules. etrievelmage") .substituteAll (HTMLtext, "src=\"" + serverRoot + "com.rnci .products .DataModules .Retrievelmage" ) ; HTMLtext = new RE("\"com.rnci.products.DataModules. etrieveAttachment" ) .substituteAll (HTMLtext, "\"" + serverRoot + "com.rnci.products.DataModules.RetrieveAttachment") ; } catch (Exception e) { System. err.println (e.getMessageO ) ; e.printStackTrace () ; } String scriptHTML = ""; int StartSearchAt = 0; int scriptLoc = indexOfIgnoreCase (HTMLtext, "<SCRIPT", startSearchAt) ; if (scriptLoc > -1) { //Check for client scripts and separate them from regular HTML try { int endScriptLoc,- int articleLength = HTMLtext. length () ; StringBuffer sbArticle = new StringBuffer (articleLength + 1); StringBu er sbScripts = new StringBuffer ( ) ; while (scriptLoc > -1) { endScriptLoc = indexOfIgnoreCase (HTMLtext, "</ΞCRIPT>" .scriptLoc) ; sbArticle.append (HTMLtext. substring (startSearchAt, scriptLoc) ) ; sbScripts. append(HTMLtext. substring( (indexOfIgnoreCase (HTMLtext, ">" .scriptLoc) +1) .endScriptLoc) ) ; sbScripts . append( ' \n' ) ; sbScripts .append( ' \r' ) ; //System. out.println("The HTML: " + HTMLtext. substring (startSearchAt, scriptLoc) ) ; //System. out.println! "The Script: " + HTMLtext.substring! (indexOfIgnoreCase (HTMLtext, ">" , scriptLoc) +1) .endScriptLoc) ) ; E-28 startSearchAt = endScriptLoc + 9; scriptLoc = indexOf IgnoreCase (HTMLtext, "<SCRIPT" , StartSearchAt) ; } sbArticle. append (HTMLtext . substring (startSearchAt, articleLength D); //System.out.println(sbArticle.toString() ) ; //System. out.println(sbScripts. toString () ) ; scriptHTML = sbScripts . toString ( ) ; //contains just the scripts' code HTMLtext = sbArticle. toString () ; //contains just the article HTML } catch (Exception e) { System.err.println(e.getMessage( ) ) ; e.printStackTrace () ,- } } HTMLtext = HTMLtext.replace('\r' , ' '); HTMLtext = HTMLtext .replace (' \n' , ' '); try { ' HTMLtext swapStrings (HTMLtext, "\\", "\\\\") HTMLtext swapStrings (HTMLtext, "\'","\W") HTMLtext swapStrings (HTMLtext, "\"","\\\"") } catch(Exception e) { System. err.println (e.getMessageO ) e.printStackTrace ( ) ; } return scriptHTML + " document.write + HTMLtext + '); } public static String swapStrings (String Textln, String OldString, String NewString) { int OldStringStartAt; int OldStringLength = OldString. lengt () ; int NewStringLength = NewString. length () ; String TempText = Textln; OldStringStartAt = indexOfIgnoreCase (TempText, OldString, 0) ,- while (OldStringStartAt != -1) { TempText = TempText . substring ( 0, OldStringStartAt) + NewString + 'empText. substring (OldStringStartAt + OldStringLength) ; OldStringStartAt = indexO IgnoreCase (TempText, OldString, OldStringStartAt + FewStringLength) ; } return TempText,- } public static int indexOfIgnoreCase (String TempText, String substring, int StartAt) { return TempText. toLowerCase () .indexOf ( substring. toLowerCase () , StartAt) ; } private String removeAllParams (String URL) { String tempURL = URL; Util myϋtil = new Util(); try { myϋtil . setOriginalURL (URL) ; myUtil . setParamToRemove ( " bdurl" ) ; tempURL = myUtil.getRemovedParamURLO ; myUtil .setOriginalURL (tempURL) ; myUtil . setParamToRemove ( " brand" ) ; tempURL = myUtil.getRemovedParamURLO ; myUtil. setOriginalURL (tempURL) ; myUtil. setParamToRemove("jbact") ; tempURL = myUtil.getRemovedParamURLO; myUtil.setOriginalURL (tempURL) ; myUtil . setParamToRemove ( "jbsid" ) ; tempURL = myUtil.getRemovedParamURLO ; myUtil .setOriginalURL (tempURL) ; myϋti1. setParamToRemove( "jbgid" ) ; tempURL = myUtil.getRemovedParamURLO ; E-29 myUtil . setOriginalURL (tempURL) ; myUtil . setParamToRemove ( "jbbid" ) ; tempURL = myUtil.getRemovedParamURLO; myUtil. setOriginalURL (tempURL) ; myUtil .setParamToRemove! "jpostbact") ; tempURL = myUtil.getRemovedParamURLO; myUtil . setOriginalURL (tempURL) ; myUtil .setParamToRemove ( "jbts" ) ; tempURL = myUtil.getRemovedParamURL ; } catch (MalformedURLException mue) { mue.printStackTraceO ; //put in garbage URL that will never match JW 12/4/00 tempURL = "error" ; } //System,out.println (tempURL) ; return tempURL; } private String parseHostFromURL (String targetURL) { StringTokenizer tokenizer = new StringTokenizer (targetURL, "/"); int tokencount = tokenizer. countTokens () ; int i; String returnHost = " " ; if (tokencount > 1) { for (i = 1; i < 3; i++) returnHost = tokenizer.nextToken!) ; } else { returnHost = " " ; } return returnHost ; } private boolean validateHost (int jbsid, String targetHost) { //false: URL - Site match found //true: bad URL boolean errFlag = false; BlurbSiteDB bs = new BlurbSiteDB () ; Vector v = null; Connection conn = dataConnMan.getConnection (server, dbname) ; try { v = bs.getAll (conn, "blurb_site_id =" + jbsid + " and upper(url) like '%" + argetHost . toUpperCase ( ) + "%'"); } catch (Exception e) { BlurbCommon.handleException (e) ; errFlag = true; } dataConnMan. freeConnection (server, dbname, conn); if (v.size!) < 1) errFlag = true; return errFlag,- } Content lookup (String contentID) { Content cont; int index = -1; for (int i=0; i<contents.size() ,- ++i) { cont = (Content) contents. elementAt (i) ; if (contentID. equals (cont.contentID) ) return (Content) contents. elementAt (i) ; } return null; } class Content { String contentID, detail; long timestamp; Content (String contentID, String detail, long timestamp) { this.contentID = contentID; this.detail = detail; this . timestamp = timeεtamp/60000; //converts milliseconds to minutes E-30 } } private class Sentinel extends Thread { int itemsToKeep; int minutesToLive; boolean quit = false; Sentinel (int itemsToKeep, int minutesToLive) { System. out. rintln ( "Sentinel Constructor " ) ,- this . itemsToKeep = itemsToKeep; this . minutesToLive = minutesToLive ; setPriority ( Thread . MIN_PRIORITY) ; start ( ) ; } public void run () { int itemsToRemove; while (iquit) { // this keeps cleanup alive until servlet is destroyed reshen ( ) ; if (contents.size() > itemsToKeep) trim(); //System. out.println (contents. size () ) ; //Syεtem.gcO ; try { Thread. sleep(5000) ; } catch (InterruptedException ex) { System, err .println (ex.getMessageO ) ; ex.printStackTrace() ,- } //System. out.printlni "Sentinel ran at:" + System. currentTimeMillis ()) ; ) } private void trim() { int iterasToRemove = contents.size() - itemsToKeep; int trimmed = 0 ; for (int i=0; i<itemsToRemove; ++i) { contents.removeElementAt (i) ; //System. out .println ( "Removed: " + contents. elementAt (i) .toString ()) ; Thread.yield ( ) ,- trimmed++ ; ) if (trimmed > 10) contents . trimToSize () ; } private void freshen () { long currentTime = System.currentTimeMillis () /60000; Content cont; for (int i=0; i<contents.size() ; ++i) { cont = (Content) contents. elementAt (i) ; if (cont. timestamp + minutesToLive < currentTime) { contents . removeElementAt (i) ; //System. out.println("Expired: " + cont.contentID) ; Thread.yield() ; } } E-31

Claims: CLAIMS 1. A method of obtaining selected content for a web page, wherein the selected content itself is not initially part ofthe web page, the web page including script associated with the selected content, the method comprising: (a) a web browser requesting a web page that includes script associated with the selected content; and (b) the web browser interpreting the script and formatting a request for obtaining the selected content from a remote site, the request including a uniform resource identifier (URI) of the web page and a unique identifier ofthe selected content. 2. A method of claim 1 further comprising: (c) a remote site receiving the request and authenticating whether the URI is authorized to receive the selected content, and, if so, the remote site locating the selected content, and sending the selected content to the web browser; and (d) the web browser assembling the initially requested web page using the selected content obtained from the remote site. 3. The method of claim 2 wherein the remote site is a web server, and the selected content is stored in a content repository connected to the web server. 4. The method of claim 2 wherein the selected content includes two or more different selected content, each selected content being used for different parts ofthe web page, wherein each selected content has its own script for implementing steps (b)-(d). 5. The method of claim 2 wherein in step (c), if the URI is not authorized to receive the selected content, the remote site sends a signal to the web browser that the selected content is not available, and the web browser assembles the web page without the selected content. 6. The method of claim 1 wherein the URI is a uniform resource locator (URL). 7. The method of claim 1 wherein the selected content is only a portion ofthe web page. 8. The method of claim 1 wherein the selected content is a digital asset. 9. The method of claim 1 wherein the selected content is an executable file. 10. The method of claim 1 wherein the script includes a subscriber identifier and a content identifier, and step (b) further comprises using the subscriber identifier and the content identifier to create the unique identifier ofthe selected content. 11. The method of claim 1 wherein the web page is constructed using HTML, and the script is embedded therein. 12. The method of claim 1 wherein the script is JavaScript. 13. A method of syndicating digital assets comprising: (a) constructing a web page; and (b) inserting into the web page script associated with at least one digital asset that is desired to be part of a fully rendered web page, wherein the script, when executed by a browser, requests the content ofthe digital asset from a remote site, the request including a uniform resource identifier (URI) ofthe web page and a unique identifier ofthe selected content. 14. A method of claim 13 wherein the script is JavaScript. 15. A method of claim 13 wherein the selected content is an executable file. 16. A method of claim 13 wherein the script includes a subscriber identifier and a content identifier, which, together, create the unique identifier ofthe selected content. 17. An article of manufacture for syndicating digital assets, the article of manufacture comprising a computer-readable medium holding computer-executable instructions for performing a method comprising: (a) constructing a web page; and (b) inserting into the web page script associated with at least one digital asset that is desired to be part of a fully rendered web page, wherein the script, when executed by a browser, requests the content ofthe digital asset from a remote site, the request including a uniform resource identifier (URI) ofthe web page and a unique identifier ofthe selected content. 18. The article of manufacture of claim 17 wherein the script is JavaScript. 19. The article of manufacture of claim 17 wherein the selected content is an executable file. 20. The article of manufacture of claim 17 wherein the script includes a subscriber identifier and a content identifier, which, together, create the unique identifier ofthe selected content. 21. An apparatus for syndicating digital assets comprising: (a) means for constructing a web page; and (b) means for inserting into the web page script associated with at least one digital asset that is desired to be part of a fully rendered web page, wherein the script, when executed by a browser, requests the content ofthe digital asset from a remote site, the request including a uniform resource identifier (URI) ofthe web page and a unique identifier ofthe selected content. 22. The apparatus of claim 21 wherein the script is JavaScript. 23. The apparatus of claim 21 wherein the selected content is an executable file. 24. The apparatus of claim 21 wherein the script includes a subscriber identifier and a content identifier, which, together, create the unique identifier ofthe selected content.

Inventors: MARTIN RICHARD D, WETZEL JOHN E, MARTIN, RICHARD, D., WETZEL, JOHN, E.
Applicants: ACTIVE DATA EXCHANGE INC, ACTIVE DATA EXCHANGE, INC.
Application year: 2001
Main classification: G06F15
IPC codes: G06F17