Friday, November 6, 2009

Sample Program-Lilt












Sample Program–Lilt

The following small program illustrates some of the basic functionality in the libnids library. Lilt is a bare-bones TCP watching tool. It offers the user the capability to monitor the network for TCP connections and TCP port scans. Once Lilt locks on to a TCP connection, the user has the option of watching or terminating the connection. Connection watching is generally only useful if the connection in question is not transaction-oriented (in other words, HTTP) and largely consists of printable ASCII characters such as Telnet or Internet Relay Chat (IRC). Lilt is pretty stupid in that no post-libnids processing on the TCP streams occurs in order to decode or analyze the data—so only textual data prints as it is found in the data portion of the TCP packet. Another major drawback of Lilt is that it can only handle a single TCP connection at a time. As soon as it sees a connection that it wants to monitor, Lilt locks on to this connection and ignores all others until it ends—either naturally or as a result of the user deciding to terminate it (optionally, the user can discard the connection by pressing D). Connection termination (via spoofed RST packets) works for any TCP connection to which libnids locks on.


Lilt is both user-input and network-driven in that it performs synchronous input/output (I/O) multiplexing across the libnids network file descriptor and standard input. Once invoked, it sits and waits for TCP activity or commands from the user. The following sample invocation of Lilt shows its command summary:



tradecraft: ~# ./lilt
Lilt 1.0 [the littlest network watcher]
TCP monitoring callback registered
Monitoring connections to the following ports: 23 6667
Libnids engine initialized, waiting for events...

<?>
-[lilt command summary]-
[?] - this blurb
d - discard connection from scope
k - kill connection
[p] - display ports being monitored
[q] - quit lilt
[s] - statistics
w - watch connection

<q>
-[later dorkus!]-

The commands available to the user appear within brackets, and the other commands are unavailable until a connection comes into scope.


Lilt also accepts a single argument: a comma-delimited list of TCP well-known ports to monitor (if this argument is omitted as it was earlier, Lilt defaults to monitoring connections to port 23 and port 6667). The following example is a sample invocation of libnids across a relatively quiet network:




tradecraft: ~# lilt -m22, 23, 6667
Lilt 1.0 [the littlest network watcher]
TCP monitoring callback registered
Monitoring connections to the following ports: 22 23 6667
Libnids engine initialized, waiting for events...

-[Dec 30 11:44:03: TCP connection: 192.168.0.94.1680 -> 10.0.0.7.23]-

<?>
-[lilt command summary]-
[?] - this blurb
[d] - discard connection from scope
[k] - kill connection
[p] - display ports being monitored
[q] - quit lilt
[s] - statistics
[w] - watch connection

<w>
-[watching connection]-
%%%%& #'$& #' $PANSI"!"!
FreeBSD/i386 (dork.parade.net) (ttyp2)

login: rroooott

Password:110v4d&D

Last login: Mon Dec 31 02:03:22 from 192.168.0.94
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights
reserved.

FreeBSD 4.1-RC (DORK) #25: Tue Jul 17 17:57:52 EDT 2001

---------------------------------------------------------------------

- Unauthorized use of this computer is really frowned upon
- If anyone has any spare 20 sided dice pls send mail to root

---------------------------------------------------------------------

You have mail.
"Deliver yesterday, code today, think tomorrow."
dork:~> llss

Mail monster-manual.pdf
dork:~>
<k>
-[killing connection]-

-[Dec 30 11:45:08: TCP connection terminated]-

-[Dec 30 11:48:13: TCP connection: 192.168.0.94.1683 ->
10.16.10.22.6667]-

<k>
-[killing connection]-

-[TCP connection terminated]-

<s>
-[lilt statistics]-
TCP connections: 2
TCP connections killed: 2
Port scans detected: 0

-[Dec 30 11:54:41: portscan detected from 192.168.0.94]-
10.0.1.3:22
10.0.1.3:23
10.0.1.3:25
10.0.0.1:80
10.0.1.3:110
10.0.1.3:135
10.0.1.3.139
10.0.1.3.443

<s>
-[lilt statistics]-
TCP connections: 2
TCP connections killed: 2
Port scans detected: 1

<q>
-[later dorkus!]-


The first connection that Lilt saw that matched its filter list was a Telnet connection (TCP/23). Notice that because a connection was in scope, all of Lilt's commands were available. The user pressed W to watch the connection and nabbed the root login and password. Shortly thereafter, the user issued a kill command (pressed the K key) to terminate the connection. The user also immediately killed the next connection (established to an IRC server [TCP/6667]). Later on, a portscan was detected; the user checked statistics and then quit the program.


One small footnote to Lilt is its slightly inconsistent behavior on different platforms. Under OpenBSD, the user notices a lag between network activity and what is displayed in "real-time" on the Lilt console. Under Linux, this lag is non-existent due to differences in how the operating systems handle libpcap read timeouts. OpenBSD supports the timeout, and Linux does not. So what is happening is that Lilt, under OpenBSD, is technically being more efficient by attempting to read many packets at once—but it is a poor performer for a real-time application (BPF buffers packets inside the kernel). Linux, while utilizing more kernel time, provides a friendlier operation to the user.


In order to fix this problem, the application programmer would have to change the libpcap timeout to 0 and call an ioctl to set the BPF device to return immediately when a packet becomes available. At this writing, because there is no high-level primitive to change the libpcap timeout in libnids, in order to make this behavior more consistent the application programmer has to modify the libnids source directly and rebuild the library. We revisit this problem (with a portable solution) in Chapter 12.















35.5. Joining a Professional Organization










 < Free Open Study > 







35.5. Joining a Professional Organization



cc2e.com/3535



One of the best ways to learn more about programming is to get in touch with other programmers who are as dedicated to the profession as you are. Local user groups for specific hardware and language products are one kind of group. Other kinds are national and international professional organizations. The most practitioner-oriented organization is the IEEE Computer Society, which publishes the IEEE Computer and IEEE Software magazines. For membership information, see http://www.computer.org.



cc2e.com/3542



The original professional organization was the ACM, which publishes Communications of the ACM and many special-interest magazines. It tends to be somewhat more academically oriented than the IEEE Computer Society. For membership information, see http://www.acm.org.












     < Free Open Study > 



    Chapter 18. Stored Program Security










    Chapter 18. Stored Program Security


    Security has always been critical in the world of databases and stored programs that work with those databases. Yet database security has taken on heightened importance in the last decade, with the global reach of the Internet and the increasing tendency for the database to be the target of those trying to compromise application security. In this chapter we explore two different aspects of security as it pertains to MySQL stored programming:


    • Controlling access to the execution and modification of stored programs themselves

    • Using stored programs to secure the underlying data in MySQL databases


    Stored programsin particular, stored proceduresare subject to most of the security restrictions that apply to other database objects, such as tables, indexes, and views. Specific permissions are required before a user can create a stored program, and, similarly, specific permissions are needed in order to execute a program.


    What sets the stored program security model apart from that of other database objectsand from other programming languagesis that stored programs may execute with the permissions of the user who created the stored program, rather than those of the user who is executing the stored program. This model allows users to execute operations via a stored program that they would not be privileged to execute using straight SQL.


    This facilitysometimes called definer rights securityallows us to tighten our database security: we can ensure that a user gains access to tables only via stored program code that restricts the types of operations that can be performed on those tables and that can implement various business and data integrity rules. For instance, by establishing a stored program as the only mechanism available for certain table inserts or updates, we can ensure that all of these operations are logged, and we can prevent any invalid data entry from making its way into the table.


    We can also create stored programs that execute with the privileges of the calling user, rather than those of the user who created the program. This mode of security is sometimes called invoker rights security, and it offers other advantages beyond those of definer rights, which we will explore in this chapter.


    Before delving into the two execution modes available in MySQL, we will first examine the basic permissions
    needed to create, manage, and execute stored programs
    . Then we'll go into a detailed discussion of definer rights and invoker rights, and consider how these capabilities might be used in our applications. Finally, we will consider the use of stored programs to increase the general security of our MySQL server and, conversely, identify ways in which the use of stored programs can reduce overall security if developers are not careful.












    A.14 Chapter 14 , Network Deployment Models



    [ Team LiB ]






    A.14 Chapter 14, Network Deployment Models



    This chapter has undergone the most extensive revisions of any
    chapter in the book; even its name has changed (from Oracle
    and The Web
    ). The Oracle Database 10g
    release claims to take Oracle beyond the Web into the grid, so in
    addition to briefly covering features described in previous
    editions�for example, Oracle Application Server[1]�it also includes a summary of
    the needs of grid computing and how the Oracle Database 10g
    release is addressing them
    .

    [1] For more information on Oracle Application Server 10g than we
    can include in this chapter, see the book Oracle
    Application Server 10g Essentials
    , expected to be released
    later in 2004.




    HTML DB



    This is a development tool for creating HTML-based applications,
    creating and modifying database structures, and importing data into
    the Oracle database.




    Direct calls to Java stored procedures



    You no longer have to create a PL/SQL wrapper to call a Java stored
    procedure.




    XML DB



    XML DB is a set of improvements for the XML capabilities of the
    Oracle database.




    Failover notification



    Oracle Application Server 10g is notified of a failure in a Real
    Application Cluster node.




    Enterprise Configuration Manager



    This tool is a part of Enterprise Manager 10g that allows you to
    discover, compare, and modify the configuration of servers across
    your enterprise.




    Application Performance Management



    This new tool allows you to set up beacons, which run user-defined
    transactions from remote locations and send the results back to the
    Enterprise Manager repository.











      [ Team LiB ]



      Section 3.3.&nbsp; Development Environment Installation










      3.3. Development Environment Installation


      The first thing you need for the tutorial is a set of tools to write the code. The Eclipse SDK has a full set of Java Development Tooling (JDT), complete with a comprehensive Plug-in Development Environment (PDE). The CD included with this book contains a complete SDK configuration for several platforms. You can use that setup, use one of your own, or download the latest release from http://eclipse.org/downloads.


      The Eclipse downloads site contains a vast array of downloads, but the Eclipse SDK is the most popular and should be highlighted on the site. The download is a zip or tar.gz with a name similar to:


      eclipse-SDK-3.1-win32.zip


      This book details function that is new to Eclipse in 3.1, the latest release as the book went to press. You must be using the released version of 3.1 or later to follow the exercises. Be sure to get the appropriate download for your machine (OS, window system, and processor). Once you have the file downloaded, expand it in some convenient location (say c:\ide on Windows) as shown in Figure 3-1.



      Figure 3-1. Development environment disk layout







      Note



      The download site does not include a Java Runtime Environment™ (JRE) or JDK, but the CD does. If you are supplying your own setup, you must ensure a compatible JRE is installed. The download page for each Eclipse SDK release includes links to common Java environments compatible with the release. To complete all of the work in this book, you should get a Java SDK (sometimes called a JDK), as it includes a couple of handy tools such as jarsigner. These are included in the SDKs on the CD.




      Now you are set to run the IDE. Double-click on the launcher (eclipse.exe or eclipse, depending on your machine). When Eclipse starts up, it asks for a workspace location. The workspace is the place where development artifacts such as projects and code are stored. It is typically a good idea to locate the workspace somewhere separate from the IDE install. This simplifies the management of multiple workspaces as well as changing versions of the Eclipse IDE. By default, Eclipse suggests a location in your user directory (e.g., c:\Documents and Settings\you\workspace). This is a fine choice.


      After you select a workspace location, Eclipse continues to start and shows the welcome page. Feel free to play around with the information there. When you are ready to continue, go to the Workbench by clicking on the arrow at the top right corner.












      A.3 Column Types











       < Day Day Up > 





      A.3 Column Types



      MySQL supports a number of column types, which may be grouped into three categories: numeric types, date and time types, and string (character) types. This section first gives an overview of the types available and summarizes the storage requirements for each column type, and then provides a more detailed description of the properties of the types in each category. The overview is intentionally brief. More detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values.



      The column types supported by MySQL follow. The following code letters are used in the descriptions:





      • M:

        Indicates the maximum display size. The maximum legal display size is 255.



      • D:

        Applies to floating-point types and indicates the number of digits following the decimal point. The maximum possible value is 30, but should be no greater than M-2.



      Square brackets ([ and ]) indicate parts of type specifiers that are optional.



      Note that if you specify ZEROFILL for a column, MySQL automatically adds the UNSIGNED attribute to the column.



      Warning:

      You should be aware that when you use subtraction between integer values where one is of type UNSIGNED, the result will be unsigned.





      • TINYINT[(M)] [UNSIGNED] [ZEROFILL]:

        A very small integer. The signed range is -128 to 127. The unsigned range is 0 to 255.



      • BIT, BOOL:

        These are synonyms for TINYINT(1).



      • SMALLINT[(M)] [UNSIGNED] [ZEROFILL]:

        A small integer. The signed range is -32768 to 32767. The unsigned range is 0 to 65535.



      • MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]:

        A medium-size integer. The signed range is -8388608 to 8388607. The unsigned range is 0 to 16777215.



      • INT[(M)] [UNSIGNED] [ZEROFILL]:

        A normal-size integer. The signed range is -2147483648 to 2147483647. The unsigned range is 0 to 4294967295.



      • INTEGER[(M)] [UNSIGNED] [ZEROFILL]:

        This is a synonym for INT. BIGINT[(M)] [UNSIGNED] [ZEROFILL]: A large integer. The signed range is -9223372036854775808 to 9223372036854775807. The unsigned range is 0 to 18446744073709551615.



      • FLOAT(precision) [UNSIGNED] [ZEROFILL]:

        A floating-point number. precision can be less than or equal to 24 for a single-precision floating-point number and between 25 and 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(X) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. Note that using FLOAT might give you some unexpected problems because all calculations in MySQL are done with double precision.



      • FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]:

        A small (single-precision) floating-point number. Allowable values are -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to 3.402823466E+38. If UNSIGNED is specified, negative values are disallowed. The M is the display width and D is the number of decimals. FLOAT without arguments or FLOAT(X) where X is less than or equal to 24 stands for a single-precision floating-point number.



      • DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]:

        A normal-size (double-precision) floating-point number. Allowable values are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to 1.7976931348623157E+308. If UNSIGNED is specified, negative values are disallowed. The M is the display width and D is the number of decimals. DOUBLE without arguments or FLOAT(X) where X is between 25 and 53 stands for a double-precision floating-point number.



      • DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL]:

        These are synonyms for DOUBLE.



      • DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]:

        An unpacked floating-point number. Behaves like a CHAR column: "unpacked" means the number is stored as a string, using one character for each digit of the value. The decimal point and, for negative numbers, the - sign, are not counted in M (but space for these is reserved). If D is 0, values will have no decimal point or fractional part. The maximum range of DECIMAL values is the same as for DOUBLE, but the actual range for a given DECIMAL column may be constrained by the choice of M and D. If UNSIGNED is specified, negative values are disallowed. If D is omitted, the default is 0. If M is omitted, the default is 10.



      • DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]:

        These are synonyms for DECIMAL.



      • DATE:

        A date. The supported range is '1000-01-01' to '9999-12-31'. MySQL displays DATE values in 'YYYY-MM-DD' format, but allows you to assign values to DATE columns using either strings or numbers.



      • DATETIME:

        A date and time combination. The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'. MySQL displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format, but allows you to assign values to DATETIME columns using either strings or numbers.



      • TIMESTAMP[(M)]:

        A timestamp. The range is '1970-01-01 00:00:00' to sometime in the year 2037.

        In MySQL 4.0 and earlier, TIMESTAMP values are displayed in YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYYYMMDD, or YYMMDD format, depending on whether M is 14 (or missing), 12, 8, or 6, but allows you to assign values to TIMESTAMP columns using either strings or numbers.

        From MySQL 4.1, TIMESTAMP is returned as a string with the format 'YYYY-MM-DD HH:MM:SS'. If you want to have this as a number, you should add +0 to the timestamp column. Different timestamp lengths are not supported. From version 4.0.12, the --new option can be used to make the server behave as in version 4.1.

        A TIMESTAMP column is useful for recording the date and time of an INSERT or UPDATE operation because it is automatically set to the date and time of the most recent operation if you don't give it a value yourself. You can also set it to the current date and time by assigning it a NULL value. The M argument affects only how a TIMESTAMP column is displayed; its values always are stored using 4 bytes each.



      • TIME:

        A time. The range is '-838:59:59' to '838:59:59'. MySQL displays TIME values in 'HH:MM:SS' format, but allows you to assign values to TIME columns using either strings or numbers.



      • YEAR[(2|4)]:

        A year in two- or four-digit format (default is four-digit). The allowable values are 1901 to 2155, 0000 in the four-digit year format, and 1970-2069 if you use the two-digit format (70-69). MySQL displays YEAR values in YYYY format, but allows you to assign values to YEAR columns using either strings or numbers.



      • [NATIONAL] CHAR(M) [BINARY]:

        A fixed-length string that is always right-padded with spaces to the specified length when stored. The range of M is 0 to 255 characters. Trailing spaces are removed when the value is retrieved. CHAR values are sorted and compared in case-insensitive fashion according to the default character set unless the BINARY keyword is given. NATIONAL CHAR (or its equivalent short form, NCHAR) is the SQL-99 way to define that a CHAR column should use the default character set. This is the default in MySQL. CHAR is shorthand for CHARACTER. MySQL allows you to create a column of type CHAR(0). This is mainly useful when you have to be compliant with some old applications that depend on the existence of a column but that do not actually use the value. This is also quite nice when you need a column that can take only two values: A CHAR(0) that is not defined as NOT NULL will occupy only 1 bit and can take two values: NULL or '' (the empty string).



      • CHAR:

        This is a synonym for CHAR(1).



      • [NATIONAL] VARCHAR(M) [BINARY]:

        A variable-length string. Note: Trailing spaces are removed when the value is stored (this differs from the SQL-99 specification). The range of M is 0 to 255 characters (1 to 255 prior to MySQL Version 4.0.2). VARCHAR values are sorted and compared in case-insensitive fashion unless the BINARY keyword is given. VARCHAR is a shorthand for CHARACTER VARYING.



      • TINYBLOB, TINYTEXT:

        A BLOB or TEXT column with a maximum length of 255 characters.



      • BLOB, TEXT:

        A BLOB or TEXT column with a maximum length of 65535 characters.



      • MEDIUMBLOB, MEDIUMTEXT:

        A BLOB or TEXT column with a maximum length of 16777215 characters.



      • LONGBLOB, LONGTEXT:

        A BLOB or TEXT column with a maximum length of 4294967295 characters. The maximum allowed length of LONGBLOB or LONGTEXT columns depends on the configured maximum packet size in the client/server protocol and available memory.



      • ENUM('value1','value2',…):

        An enumeration. A string object that can have only one value, chosen from the list of values 'value1', 'value2', , NULL or the special '' error value. An ENUM column can have a maximum of 65535 distinct values.



      • SET('value1','value2',…):

        A set. A string object that can have zero or more values, each of which must be chosen from the list of values 'value1', 'value2', A SET column can have a maximum of 64 members.













         < Day Day Up > 



        Chapter 11. Modeling a Class's Internal Structure: Composite Structures










        Chapter 11. Modeling a Class's Internal Structure: Composite Structures


        Sometimes the primary UML diagrams, such as class and sequence diagrams, aren't a perfect match for capturing certain details about your system. Composite structures help fill some of those gaps. Composite structures show how objects create a big picture. They model how objects work together inside a class, or how objects achieve a goal. Composite structures are fairly advanced, but they're good to have in your bag of tricks because they are perfectly suited for specific modeling situations, such as showing:




        Internal structures


        Show the parts contained by a class and the relationships between the parts; this allows you to show context-sensitive relationships, or relationships that hold in the context of a containing class




        Ports


        Show how a class is used on your system with ports




        Collaborations


        Show design patterns in your software and, more generally, objects cooperating to achieve a goal



        Composite structures provide a view of your system's parts and form part of the logical view of your system's model, as shown in Figure 11-1.












        Server-Side Includes




        [ Team LiB ]









        Server-Side Includes


        Server-side includes (SSI) are a wonderful device for saving time and space in web page design.[1] SSI are placeholders that dynamically include data within your page as the server parses the file. Here's the syntax of an SSI command:


        [1] Apache Software Foundation, "Apache Tutorial: Introduction to Server-Side Includes" [online], (Forest Hill, MD: Apache Software Foundation, 2002 [cited 13 November 2002]), available from the Internet at http://httpd.apache.org/docs-2.0/howto/ssi.html.



        <!--#element attribute="value" -->

        The element is a predefined SSI function, like echo, exec, or include, that uses the attribute and value parameters. You can include and change snippets of HTML site-wide with one SSI in each page. You also can add optimized dynamic content with SSI based on time or browser characteristics. That's where XSSI comes in.


        Conditional SSI


        With eXtended Server-Side Includes (XSSI), available in Apache 1.2 and above, Apache added the ability to include conditional logic within your pages, based on environment variables set by the server or within the HTML page itself. Conditional if/else logic adds "flow control" to your pages, allowing you to jazz up your site�with browser-dependent content, randomized links or messages, and timestamps in various formats�and ultimately create modularized pages.[2]


        [2] Webmonkey, "HotWired's XSSI Extensions" [online], (Waltham, MA: Terra Lycos, 1999), available from the Internet at http://hotwired.lycos.com/webmonkey/99/10/index0a.html.


        Here is a simple example:



        <!--#if expr="${HTTP_USER_AGENT}= /Mac/" -->
        Mac code goes here
        <!--#else -->
        Non-Mac code goes here
        <!--#endif -->


        Setting and Testing Environment Variables


        The CGI specification introduced the notion of a standard set of environment variables that are used to communicate between servers and CGI scripts.[3] Environment variables include SERVER_NAME, QUERY_STRING, and CONTENT_LENGTH. In addition, the server sets environment variables based on the headers received from the client, prefixed with the string HTTP_.[4] The HTTP_USER_AGENT string holds information about the client requesting the resource from the server (browser, version, and platform). For example, for Internet Explorer 5.0 on my Macintosh PowerBook, the HTTP_USER_AGENT string looks like this:


        [3] NCSA, "The CGI Specification" [online], (Champaign, IL: NCSA, 1995), available from the Internet at http://hoohoo.ncsa.uiuc.edu/cgi/interface.html.


        [4] Roy T. Fielding et al., "Hypertext Transfer Protocol�HTTP/1.1," RFC 2616 [online], (Reston, VA: The Internet Society, 1999), available from the Internet at http://www.ietf.org/rfc/rfc2616.txt. Defines the HTTP 1.1 protocol for "stateless" web server software. Also specifies what header information is sent from the client to the server.



        Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)

        You can parse this user agent string to extract information about the client requesting a particular page. Apache extends the standard set of environment variables with their own named variables and gives you the ability to set your own with the set directive.[5]


        [5] Apache Software Foundation, "Environment Variables in Apache" [online], (Forest Hill, MD: Apache Software Foundation, 2002 [cited 13 November 2002]), available from the Internet at http://httpd.apache.org/docs-2.0/env.html.



        <!--#set var="isDOM" value="true" -->

        You can use these variables within the same HTML file or automatically pass them to included HTML files to create nested includes. Here is an example:



        <!--#if expr="${HTTP_USER_AGENT} = /Gecko/" -->
        <!--#set var="isDOM" value="true" -->
        <!--#endif -->

        To reference variables, you use the dollar sign ($).To use this new isDOM variable, you would write:



        <!--#if expr="${isDOM}" -->
        DOM code goes here
        <!--#else -->
        non-DOM code goes here
        <!--#endif -->

        Once you've got your variables set up, you can perform comparison operations, like AND (&&) and OR (||). Here is an example:



        <!--#if expr="(${isIE5} && ${isMAC})" -->

        You can see where this is going: server-side browser sniffing.









          [ Team LiB ]



          Appendix A. Solutions to Selected Exercises

          Team-Fly
           

           

          TCP/IP Illustrated, Volume 2: The Implementation
          By
          Gary R. Wright, W. Richard Stevens
          Table of Contents


          Appendix A. Solutions to Selected Exercises


            Chapter 1

            Chapter 2

            Chapter 3

            Chapter 4

            Chapter 5

            Chapter 6

            Chapter 7

            Chapter 8

            Chapter 9

            Chapter 10

            Chapter 11

            Chapter 12

            Chapter 13

            Chapter 14

            Chapter 15

            Chapter 16

            Chapter 17

            Chapter 18

            Chapter 19

            Chapter 20

            Chapter 21

            Chapter 22

            Chapter 23

            Chapter 24

            Chapter 25

            Chapter 26

            Chapter 27

            Chapter 28

            Chapter 29

            Chapter 30

            Chapter 31

            Chapter 32


          Team-Fly
           

           
          Top
           


          Section 14.5.&nbsp; I/O Multiplexing










          14.5. I/O Multiplexing


          When we read from one descriptor and write to another, we can use blocking I/O in a loop, such as




          while ((n = read(STDIN_FILENO, buf, BUFSIZ)) > 0)
          if (write(STDOUT_FILENO, buf, n) != n)
          err_sys("write error");



          We see this form of blocking I/O over and over again. What if we have to read from two descriptors? In this case, we can't do a blocking read on either descriptor, as data may appear on one descriptor while we're blocked in a read on the other. A different technique is required to handle this case.


          Let's look at the structure of the telnet(1) command. In this program, we read from the terminal (standard input) and write to a network connection, and we read from the network connection and write to the terminal (standard output). At the other end of the network connection, the telnetd daemon reads what we typed and presents it to a shell as if we were logged in to the remote machine. The telnetd daemon sends any output generated by the commands we type back to us through the telnet command, to be displayed on our terminal. Figure 14.20 shows a picture of this.



          Figure 14.20. Overview of telnet program







          The telnet process has two inputs and two outputs. We can't do a blocking read on either of the inputs, as we never know which input will have data for us.


          One way to handle this particular problem is to divide the process in two pieces (using fork), with each half handling one direction of data. We show this in Figure 14.21. (The cu(1) command provided with System V's uucp communication package was structured like this.)



          Figure 14.21. The telnet program using two processes







          If we use two processes, we can let each process do a blocking read. But this leads to a problem when the operation terminates. If an end of file is received by the child (the network connection is disconnected by the telnetd daemon), then the child terminates, and the parent is notified by the SIGCHLD signal. But if the parent terminates (the user enters an end of file at the terminal), then the parent has to tell the child to stop. We can use a signal for this (SIGUSR1, for example), but it does complicate the program somewhat.


          Instead of two processes, we could use two threads in a single process. This avoids the termination complexity, but requires that we deal with synchronization between the threads, which could add more complexity than it saves.


          We could use nonblocking I/O in a single process by setting both descriptors nonblocking and issuing a read on the first descriptor. If data is present, we read it and process it. If there is no data to read, the call returns immediately. We then do the same thing with the second descriptor. After this, we wait for some amount of time (a few seconds, perhaps) and then try to read from the first descriptor again. This type of loop is called polling. The problem is that it wastes CPU time. Most of the time, there won't be data to read, so we waste time performing the read system calls. We also have to guess how long to wait each time around the loop. Although it works on any system that supports nonblocking I/O, polling should be avoided on a multitasking system.


          Another technique is called asynchronous I/O. To do this, we tell the kernel to notify us with a signal when a descriptor is ready for I/O. There are two problems with this. First, not all systems support this feature (it is an optional facility in the Single UNIX Specification). System V provides the SIGPOLL signal for this technique, but this signal works only if the descriptor refers to a STREAMS device. BSD has a similar signal, SIGIO, but it has similar limitations: it works only on descriptors that refer to terminal devices or networks. The second problem with this technique is that there is only one of these signals per process (SIGPOLL or SIGIO). If we enable this signal for two descriptors (in the example we've been talking about, reading from two descriptors), the occurrence of the signal doesn't tell us which descriptor is ready. To determine which descriptor is ready, we still need to set each nonblocking and try them in sequence. We describe asynchronous I/O briefly in Section 14.6.


          A better technique is to use I/O multiplexing. To do this, we build a list of the descriptors that we are interested in (usually more than one descriptor) and call a function that doesn't return until one of the descriptors is ready for I/O. On return from the function, we are told which descriptors are ready for I/O.


          Three functionspoll, pselect, and selectallow us to perform I/O multiplexing. Figure 14.22 summarizes which platforms support them. Note that select is defined by the base POSIX.1 standard, but poll is an XSI extension to the base.


          Figure 14.22. I/O multiplexing supported by various UNIX systems

          System

          poll

          pselect

          select

          <sys/select.h>

          SUS

          XSI

          FreeBSD 5.2.1

           

          Linux 2.4.22

          Mac OS X 10.3

           

          Solaris 9

           




          POSIX specifies that <sys/select> be included to pull the information for select into your program. Historically, however, we have had to include three other header files, and some of the implementations haven't yet caught up to the standard. Check the select manual page to see what your system supports. Older systems require that you include <sys/types.h>, <sys/time.h>, and <unistd.h>.


          I/O multiplexing was provided with the select function in 4.2BSD. This function has always worked with any descriptor, although its main use has been for terminal I/O and network I/O. SVR3 added the poll function when the STREAMS mechanism was added. Initially, however, poll worked only with STREAMS devices. In SVR4, support was added to allow poll to work on any descriptor.




          14.5.1. select and pselect Functions


          The select function lets us do I/O multiplexing under all POSIX-compatible platforms. The arguments we pass to select tell the kernel


          • Which descriptors we're interested in.

          • What conditions we're interested in for each descriptor. (Do we want to read from a given descriptor? Do we want to write to a given descriptor? Are we interested in an exception condition for a given descriptor?)

          • How long we want to wait. (We can wait forever, wait a fixed amount of time, or not wait at all.)


          On the return from select, the kernel tells us


          • The total count of the number of descriptors that are ready

          • Which descriptors are ready for each of the three conditions (read, write, or exception condition)


          With this return information, we can call the appropriate I/O function (usually read or write) and know that the function won't block.



          [View full width]

          #include <sys/select.h>

          int select(int maxfdp1, fd_set *restrict readfds,
          fd_set *restrict writefds, fd_set
          *restrict exceptfds,
          struct timeval *restrict tvptr);


          Returns: count of ready descriptors, 0 on timeout, 1 on error



          Let's look at the last argument first. This specifies how long we want to wait:




          struct timeval {
          long tv_sec; /* seconds */
          long tv_usec; /* and microseconds */
          };



          There are three conditions.




          tvptr == NULL




          Wait forever. This infinite wait can be interrupted if we catch a signal. Return is made when one of the specified descriptors is ready or when a signal is caught. If a signal is caught, select returns 1 with errno set to EINTR.





          tvptr->tv_sec == 0 && tvptr->tv_usec == 0




          Don't wait at all. All the specified descriptors are tested, and return is made immediately. This is a way to poll the system to find out the status of multiple descriptors, without blocking in the select function.





          tvptr->tv_sec != 0 || tvptr->tv_usec != 0




          Wait the specified number of seconds and microseconds. Return is made when one of the specified descriptors is ready or when the timeout value expires. If the timeout expires before any of the descriptors is ready, the return value is 0. (If the system doesn't provide microsecond resolution, the tvptr>tv_usec value is rounded up to the nearest supported value.) As with the first condition, this wait can also be interrupted by a caught signal.



          POSIX.1 allows an implementation to modify the timeval structure, so after select returns, you can't rely on the structure containing the same values it did before calling select. FreeBSD 5.2.1, Mac OS X 10.3, and Solaris 9 all leave the structure unchanged, but Linux 2.4.22 will update it with the time remaining if select returns before the timeout value expires.




          The middle three argumentsreadfds, writefds, and exceptfdsare pointers to descriptor sets. These three sets specify which descriptors we're interested in and for which conditions (readable, writable, or an exception condition). A descriptor set is stored in an fd_set data type. This data type is chosen by the implementation so that it can hold one bit for each possible descriptor. We can consider it to be just a big array of bits, as shown in Figure 14.23.



          Figure 14.23. Specifying the read, write, and exception descriptors for select







          The only thing we can do with the fd_set data type is allocate a variable of this type, assign a variable of this type to another variable of the same type, or use one of the following four functions on a variable of this type.




          #include <sys/select.h>

          int FD_ISSET(int fd, fd_set *fdset);


          Returns: nonzero if fd is in set, 0 otherwise



          void FD_CLR(int fd, fd_set *fdset);
          void FD_SET(int fd, fd_set *fdset);
          void FD_ZERO(fd_set *fdset);





          These interfaces can be implemented as either macros or functions. An fd_set is set to all zero bits by calling FD_ZERO. To turn on a single bit in a set, we use FD_SET. We can clear a single bit by calling FD_CLR. Finally, we can test whether a given bit is turned on in the set with FD_ISSET.


          After declaring a descriptor set, we must zero the set using FD_ZERO. We then set bits in the set for each descriptor that we're interested in, as in




          fd_set rset;
          int fd;

          FD_ZERO(&rset);
          FD_SET(fd, &rset);
          FD_SET(STDIN_FILENO, &rset);



          On return from select, we can test whether a given bit in the set is still on using FD_ISSET:




          if (FD_ISSET(fd, &rset)) {
          ...
          }



          Any (or all) of the middle three arguments to select (the pointers to the descriptor sets) can be null pointers if we're not interested in that condition. If all three pointers are NULL, then we have a higher precision timer than provided by sleep. (Recall from Section 10.19 that sleep waits for an integral number of seconds. With select, we can wait for intervals less than 1 second; the actual resolution depends on the system's clock.) Exercise 14.6 shows such a function.


          The first argument to select, maxfdp1, stands for "maximum file descriptor plus 1." We calculate the highest descriptor that we're interested in, considering all three of the descriptor sets, add 1, and that's the first argument. We could just set the first argument to FD_SETSIZE, a constant in <sys/select.h> that specifies the maximum number of descriptors (often 1,024), but this value is too large for most applications. Indeed, most applications probably use between 3 and 10 descriptors. (Some applications need many more descriptors, but these UNIX programs are atypical.) By specifying the highest descriptor that we're interested in, we can prevent the kernel from going through hundreds of unused bits in the three descriptor sets, looking for bits that are turned on.


          As an example, Figure 14.24 shows what two descriptor sets look like if we write




          fd_set readset, writeset;

          FD_ZERO(&readset);
          FD_ZERO(&writeset);
          FD_SET(0, &readset);
          FD_SET(3, &readset);
          FD_SET(1, &writeset);
          FD_SET(2, &writeset);
          select(4, &readset, &writeset, NULL, NULL);




          Figure 14.24. Example descriptor sets for select







          The reason we have to add 1 to the maximum descriptor number is that descriptors start at 0, and the first argument is really a count of the number of descriptors to check (starting with descriptor 0).


          There are three possible return values from select.


          1. A return value of 1 means that an error occurred. This can happen, for example, if a signal is caught before any of the specified descriptors are ready. In this case, none of the descriptor sets will be modified.

          2. A return value of 0 means that no descriptors are ready. This happens if the time limit expires before any of the descriptors are ready. When this happens, all the descriptor sets will be zeroed out.

          3. A positive return value specifies the number of descriptors that are ready. This value is the sum of the descriptors ready in all three sets, so if the same descriptor is ready to be read and written, it will be counted twice in the return value. The only bits left on in the three descriptor sets are the bits corresponding to the descriptors that are ready.


          We now need to be more specific about what "ready" means.


          • A descriptor in the read set (readfds) is considered ready if a read from that descriptor won't block.

          • A descriptor in the write set (writefds) is considered ready if a write to that descriptor won't block.

          • A descriptor in the exception set (exceptfds) is considered ready if an exception condition is pending on that descriptor. Currently, an exception condition corresponds to either the arrival of out-of-band data on a network connection or certain conditions occurring on a pseudo terminal that has been placed into packet mode. (Section 15.10 of Stevens [1990] describes this latter condition.)

          • File descriptors for regular files always return ready for reading, writing, and exception conditions.


          It is important to realize that whether a descriptor is blocking or not doesn't affect whether select blocks. That is, if we have a nonblocking descriptor that we want to read from and we call select with a timeout value of 5 seconds, select will block for up to 5 seconds. Similarly, if we specify an infinite timeout, select blocks until data is ready for the descriptor or until a signal is caught.


          If we encounter the end of file on a descriptor, that descriptor is considered readable by select. We then call read and it returns 0, the way to signify end of file on UNIX systems. (Many people incorrectly assume that select indicates an exception condition on a descriptor when the end of file is reached.)


          POSIX.1 also defines a variant of select called pselect.



          [View full width]

          #include <sys/select.h>

          int pselect(int maxfdp1, fd_set *restrict readfds,
          fd_set *restrict writefds, fd_set
          *restrict exceptfds,
          const struct timespec *restrict tsptr,
          const sigset_t *restrict sigmask);


          Returns: count of ready descriptors, 0 on timeout, 1 on error



          The pselect function is identical to select, with the following exceptions.


          • The timeout value for select is specified by a timeval structure, but for pselect, a timespec structure is used. (Recall the definition of the timespec structure in Section 11.6.) Instead of seconds and microseconds, the timespec structure represents the timeout value in seconds and nanoseconds. This provides a higher-resolution timeout if the platform supports that fine a level of granularity.

          • The timeout value for pselect is declared const, and we are guaranteed that its value will not change as a result of calling pselect.

          • An optional signal mask argument is available with pselect. If sigmask is null, pselect behaves as select does with respect to signals. Otherwise, sigmask points to a signal mask that is atomically installed when pselect is called. On return, the previous signal mask is restored.




          14.5.2. poll Function


          The poll function is similar to select, but the programmer interface is different. As we'll see, poll is tied to the STREAMS system, since it originated with System V, although we are able to use it with any type of file descriptor.



          [View full width]

          #include <poll.h>

          int poll(struct pollfd fdarray[], nfds_t nfds, int
          timeout);


          Returns: count of ready descriptors, 0 on timeout, 1 on error



          With poll, instead of building a set of descriptors for each condition (readability, writability, and exception condition), as we did with select, we build an array of pollfd structures, with each array element specifying a descriptor number and the conditions that we're interested in for that descriptor:




          struct pollfd {
          int fd; /* file descriptor to check, or <0 to ignore */
          short events; /* events of interest on fd */
          short revents; /* events that occurred on fd */
          };



          The number of elements in the fdarray array is specified by nfds.



          Historically, there have been differences in how the nfds parameter was declared. SVR3 specified the number of elements in the array as an unsigned long, which seems excessive. In the SVR4 manual [AT&T 1990d], the prototype for poll showed the data type of the second argument as size_t. (Recall the primitive system data types, Figure 2.20.) But the actual prototype in the <poll.h> header still showed the second argument as an unsigned long. The Single UNIX Specification defines the new type nfds_t to allow the implementation to select the appropriate type and hide the details from applications. Note that this type has to be large enough to hold an integer, since the return value represents the number of entries in the array with satisfied events.


          The SVID corresponding to SVR4 [AT&T 1989] showed the first argument to poll as struct pollfd fdarray[], whereas the SVR4 manual page [AT&T 1990d] showed this argument as struct pollfd *fdarray. In the C language, both declarations are equivalent. We use the first declaration to reiterate that fdarray points to an array of structures and not a pointer to a single structure.



          To tell the kernel what events we're interested in for each descriptor, we have to set the events member of each array element to one or more of the values in Figure 14.25. On return, the revents member is set by the kernel, specifying which events have occurred for each descriptor. (Note that poll doesn't change the events member. This differs from select, which modifies its arguments to indicate what is ready.)


          Figure 14.25. The events and revents flags for poll

          Name

          Input to events?

          Result from revents?

          Description

          POLLIN

          Data other than high priority can be read without blocking (equivalent to POLLRDNORM|POLLRDBAND).

          POLLRDNORM

          Normal data (priority band 0) can be read without blocking.

          POLLRDBAND

          Data from a nonzero priority band can be read without blocking.

          POLLPRI

          High-priority data can be read without blocking.

          POLLOUT

          Normal data can be written without blocking.

          POLLWRNORM

          Same as POLLOUT.

          POLLWRBAND

          Data for a nonzero priority band can be written without blocking.

          POLLERR

           

          An error has occurred.

          POLLHUP

           

          A hangup has occurred.

          POLLNVAL

           

          The descriptor does not reference an open file.



          The first four rows of Figure 14.25 test for readability, the next three test for writability, and the final three are for exception conditions. The last three rows in Figure 14.25 are set by the kernel on return. These three values are returned in revents when the condition occurs, even if they weren't specified in the events field.


          When a descriptor is hung up (POLLHUP), we can no longer write to the descriptor. There may, however, still be data to be read from the descriptor.


          The final argument to poll specifies how long we want to wait. As with select, there are three cases.




          timeout == -1




          Wait forever. (Some systems define the constant INFTIM in <stropts.h> as 1.) We return when one of the specified descriptors is ready or when a signal is caught. If a signal is caught, poll returns 1 with errno set to EINTR.





          timeout == 0




          Don't wait. All the specified descriptors are tested, and we return immediately. This is a way to poll the system to find out the status of multiple descriptors, without blocking in the call to poll.





          timeout > 0




          Wait timeout milliseconds. We return when one of the specified descriptors is ready or when the timeout expires. If the timeout expires before any of the descriptors is ready, the return value is 0. (If your system doesn't provide millisecond resolution, timeout is rounded up to the nearest supported value.)



          It is important to realize the difference between an end of file and a hangup. If we're entering data from the terminal and type the end-of-file character, POLLIN is turned on so we can read the end-of-file indication (read returns 0). POLLHUP is not turned on in revents. If we're reading from a modem and the telephone line is hung up, we'll receive the POLLHUP notification.


          As with select, whether a descriptor is blocking or not doesn't affect whether poll blocks.




          Interruptibility of select and poll


          When the automatic restarting of interrupted system calls was introduced with 4.2BSD (Section 10.5), the select function was never restarted. This characteristic continues with most systems even if the SA_RESTART option is specified. But under SVR4, if SA_RESTART was specified, even select and poll were automatically restarted. To prevent this from catching us when we port software to systems derived from SVR4, we'll always use the signal_intr function (Figure 10.19) if the signal could interrupt a call to select or poll.



          None of the implementations described in this book restart poll or select when a signal is received, even if the SA_RESTART flag is used.












            Who Is the Enemy?













            Who Is the Enemy?

            I'm going to arbitrarily lump potential attackers into three groups: script kiddies, disaffected users, and skilled attackers. You will find more fine-grained profiles in books dedicated to network security, but these categories are easily explained, are easily understood, and encompass 99 percent of all the attackers you're likely to encounter.




            Script Kiddies


            The most numerous attackers are script kiddies (often called "script kitties" in the OpenBSD community). Script kiddies are not sysadmins: They are not skilled and most have absolutely no idea what the heck they are doing. They download small attack programs that work on a point-and-click basis and go looking for systems that the program works on. They're the equivalent of drive-by shooters looking for easy targets. Fortunately, script kiddies are particularly easy to attack against; keeping your programs securely up-to-date will deter most of them.


            The other two groups can use any attack that can be used by script kiddies.






            Disaffected Users


            The second group causes the majority of security problems I've dealt with — a system's legitimate users. Disaffected employees and users know where a system's problems are, and are frequently able to use those problems to their own advantage. If your support people use a password-free modem in a back closet to access the computers, and you have to fire one of them, you may well have unexpected calls at that modem! The ex-employee wouldn't even have to call it himself; he could just post the phone number somewhere on the Internet and let the script kiddies go wild. Or perhaps some company administrator gives the phone number to their child so they can get Internet access, and that child shares the phone number with friends. While an unsecured modem might be an extreme example, almost every network has some "fix" that was hurriedly and thoughtlessly implemented and that can be exploited by a motivated person who knows about it.


            The best way to stop these people is to not be sloppy. Keep your systems up-to-date. When someone leaves the company change all administrative passwords, disable any accounts that person had, and tell all employees that the person has left and not to share information with him. And get rid of the unsecured modem, or the decrepit SunOS server with a telnet port open to the world, or whatever hurried hack you put into place thinking that nobody would ever find it.


            A skilled attacker can probably use any attack available to a disaffected user.





            Skilled Attackers


            The last group is actually fairly dangerous: skilled attackers. These are competent systems administrators, security researchers, and penetration specialists who want access to your systems in particular. If one of these people wants into your network, they stand a very good chance of finding any holes that exist and getting in.


            Still, the security measures that will stop the first two groups cold can change the tactics that skilled attackers must use. If you secure your network well, the intruder will have to show up at the door dressed as a telephone company repairman lugging a packet sniffer or dumpster-dive for old sticky notes with passwords scribbled on them, rather than break in via the network. This dramatically raises his exposure and can even make a break-in more trouble than it's worth.





            Hackers


            You'll frequently hear the word "hacker" used to describe people who break into computers. This word has different meanings, depending on the speaker. In the technical world, a hacker is someone who is interested in the inner workings of things. Some hackers are interested in everything; some have a narrow field of interest. In the open source community, "hacker" is generally a title of respect. In the popular media, a hacker breaks into computers. I recommend entirely avoiding the word so as to avoid confusion. In this book, I call people who break into computers "intruders." (In person I call them a variety of names that No Starch Press has yet to print in any of their books.)












            Chapter�3.� PROGRAMMING BY INTENTION









































            Prev don't be afraid of buying books Next






























            Chapter 3. PROGRAMMING BY
            INTENTION








            'Tis but thy name that
            is my enemy;




            ...




            O, be some other
            name!



            Romeo and
            Juliet, Act 2 Scene 2 William Shakespeare





            This chapter discusses programming by intention, a central idea
            in XP. It means making your intent clear when you write code.



            Have you ever had to work on a piece of code and
            found that it was hard to understand? Maybe the logic was
            convoluted, the identifiers meaningless, or worse, misleading. You
            say there was documentation? Was it readable? Did it make sense?
            Was it up to date with the code? Are you sure? How do you know?



            The main idea of programming by intention is
            communication, specifically, the communication of our intent to whomever may be reading the
            code. The goal is to enable them to understand what we had in mind
            when we wrote the code.



            Let's look at what we need to do in order to
            have our code be as understandable and intent-revealing as
            possible.















































            Amazon






            Summary











             < Day Day Up > 











            Summary




            • There are many general definitions of design. Each emphasizes different aspects of the vast range of design practices.




            • Our definition of design emphasizes the creation of meaningful experience:



              Design is the process by which a designer creates a context to be encountered by a participant, from which meaning emerges.





            • Semiotics is the study of meaning. It is primarily concerned with the question of how signs represent, or denote.




            • People use signs to designate objects or ideas. Because a sign represents something other than itself, we take the representation as the meaning of the sign.




            • Charles Pierce identifies four semiotic concepts:




              1. A sign represents something other than itself.




              2. Signs are interpreted.




              3. Meaning results when a sign is interpreted.




              4. Context shapes interpretation.







              • A sign represents something other than itself: In a game, gestures, objects, behaviors, and other elements act as signs. In the game Assassin, a tap denotes a "kill."





              • Signs are interpreted: A sign stands for something to somebody. Meaning emerges in a game as players take on active roles as interpreters of the game's signs.




              • Meaning results when a sign is interpreted: A sign stands for something to somebody in some respect or capacity. The meaning of a sign emerges from relationships between elements of a system.





              • Context shapes interpretation: Context is the environment of a sign that affects interpretation. The related phenomenon of structure also shapes interpretation. Structure is a set of rules or guidelines that prescribe how signs can be combined.























             < Day Day Up > 



            16.2 Large Tables with Paging




            I l@ve RuBoard










            16.2 Large Tables with Paging




            Working conveniently with
            very large tables can be a pain. Scrolling up and down is fine as
            long as the table is only a few hundred lines long, but when it gets
            larger, a tiny movement in the scrollbar can change your position by
            a few thousand rows. One way to solve this is by combining paging
            with scrolling. We'll create a table with 10,000
            rows (large enough to make scrolling through the entire table a
            hassle) and add buttons to page up and down 100 rows at a time.
            Within any group of 100 rows, you can use the scrollbar as usual to
            move around. Figure 16-2 shows the result.




            Figure 16-2. A paging (and scrolling) table



            In this example, we're using a simple trick. There
            are really two tables to worry about: a logical table that contains
            all 10,000 rows, which might represent records that were read from a
            database, and the physical table that's instantiated
            as a JTable object and displayed on the screen. To
            do this trick, we implement a new table model,
            PagingModel, which is a subclass of
            AbstractTableModel. This table model keeps track
            of the data for the entire logical table: all 10,000 rows. However,
            when a JTable asks it for data to display, it
            pretends it knows only about the 100 rows that should be on the
            screen at this time. It's actually quite simple.
            (And we don't even need to worry about any column
            models; the default column model is adequate.)



            Here's the PagingModel code used
            to track the 10,000 records:



            // PagingModel.java
            // A larger table model that performs "paging" of its data. This model reports a
            // small number of rows (e.g., 100 or so) as a "page" of data. You can switch pages
            // to view all of the rows as needed using the pageDown( ) and pageUp( ) methods.
            // Presumably, access to the other pages of data is dictated by other GUI elements
            // such as up/down buttons, or maybe a text field that allows you to enter the page
            // number you want to display.
            //
            import javax.swing.table.*;
            import javax.swing.*;
            import java.awt.event.*;
            import java.awt.*;

            public class PagingModel extends AbstractTableModel {

            protected int pageSize;
            protected int pageOffset;
            protected Record[] data;

            public PagingModel( ) {
            this(10000, 100);
            }

            public PagingModel(int numRows, int size) {
            data = new Record[numRows];
            pageSize = size;

            // Fill our table with random data (from the Record( ) constructor).
            for (int i=0; i < data.length; i++) {
            data[i] = new Record( );
            }
            }

            // Return values appropriate for the visible table part.
            public int getRowCount( ) { return Math.min(pageSize, data.length); }
            public int getColumnCount( ) { return Record.getColumnCount( ); }

            // Work only on the visible part of the table.
            public Object getValueAt(int row, int col) {
            int realRow = row + (pageOffset * pageSize);
            return data[realRow].getValueAt(col);
            }

            public String getColumnName(int col) {
            return Record.getColumnName(col);
            }

            // Use this method to figure out which page you are on.
            public int getPageOffset( ) { return pageOffset; }

            public int getPageCount( ) {
            return (int)Math.ceil((double)data.length / pageSize);
            }

            // Use this method if you want to know how big the real table is. You could also
            // write "getRealValueAt( )" if needed.
            public int getRealRowCount( ) {
            return data.length;
            }

            public int getPageSize( ) { return pageSize; }
            public void setPageSize(int s) {
            if (s == pageSize) { return; }
            int oldPageSize = pageSize;
            pageSize = s;
            pageOffset=(oldPageSize * pageOffset) / pageSize;
            fireTableDataChanged( );
            }

            // Update the page offset and fire a data changed event (all rows).
            public void pageDown( ) {
            if (pageOffset < getPageCount( ) - 1) {
            pageOffset++;
            fireTableDataChanged( );
            }
            }

            // Update the page offset and fire a data changed (all rows).
            public void pageUp( ) {
            if (pageOffset > 0) {
            pageOffset--;
            fireTableDataChanged( );
            }
            }

            // We provide our own version of a scrollpane that includes
            // the Page Up and Page Down buttons by default.
            public static JScrollPane createPagingScrollPaneForTable(JTable jt) {
            JScrollPane jsp = new JScrollPane(jt);
            TableModel tmodel = jt.getModel( );

            // Don't choke if this is called on a regular table . . .
            if (! (tmodel instanceof PagingModel)) {
            return jsp;
            }

            // Go ahead and build the real scrollpane.
            final PagingModel model = (PagingModel)tmodel;
            final JButton upButton = new JButton(new ArrowIcon(ArrowIcon.UP));
            upButton.setEnabled(false); // Starts off at 0, so can't go up
            final JButton downButton = new JButton(new ArrowIcon(ArrowIcon.DOWN));
            if (model.getPageCount( ) <= 1) {
            downButton.setEnabled(false); // One page...can't scroll down
            }

            upButton.addActionListener(new ActionListener( ) {
            public void actionPerformed(ActionEvent ae) {
            model.pageUp( );

            // If we hit the top of the data, disable the Page Up button.
            if (model.getPageOffset( ) == 0) {
            upButton.setEnabled(false);
            }
            downButton.setEnabled(true);
            }
            } );

            downButton.addActionListener(new ActionListener( ) {
            public void actionPerformed(ActionEvent ae) {
            model.pageDown( );

            // If we hit the bottom of the data, disable the Page Down button.
            if (model.getPageOffset( ) == (model.getPageCount( ) - 1)) {
            downButton.setEnabled(false);
            }
            upButton.setEnabled(true);
            }
            } );

            // Turn on the scrollbars; otherwise, we won't get our corners.
            jsp.setVerticalScrollBarPolicy
            (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            jsp.setHorizontalScrollBarPolicy
            (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

            // Add in the corners (page up/down).
            jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
            jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);

            return jsp;
            }
            }




            The PagingModel constructor fills an array with
            all our data. (The Record object does something
            simple to generate meaningless data; in real life, we could be
            getting data from a database, J2EE call, XML-RPC, or any number of
            live sources.) Most of the methods in the
            PagingModel are fairly self-explanatory. The
            interesting ones have something to do with the
            table's rows. getRowCount( )
            isn't computationally complex, but is typical of
            what we'll see: if the table is too big for one
            page, it returns pageSize, which is the number of
            rows we want to display. getValueAt( ) is only
            slightly more complex: it translates the desired row from the
            physical table into the actual row within the much larger logical
            table and returns the appropriate data. (We don't
            need to do anything to the column, but we would if we were making a
            table that paged in two directions.) We've added
            some convenience methods�getPageOffset( ),
            getPageCount( ), and getRealRowCount( )�to provide information about the
            table's actual size and the portion
            we're looking at.



            The pageDown( ) and pageUp( )
            methods are a bit more interesting. These are called when the user
            clicks on either of the paging buttons displayed with the table. When
            the user pages, these methods increment or decrement the
            model's pageOffset variable,
            which records the current offset into the table. This effectively
            means that the data in the physical table (the table we display) has
            changed, although nothing has changed in the logical table at all.
            Because the physical table has changed, we call
            fireTableDataChanged( ), which fires a
            TableModelEvent that tells the
            JTable to reload all the data. When
            it's created, the JTable
            registers itself as a listener for table model events.



            Our table doesn't let you change the page increment,
            but that would be a useful feature, so we provide a
            setPageSize( ) method. This method is interesting
            because, again, changing the page size does nothing to the logical
            table, but it effectively adds or deletes rows from the physical
            JTable on the screen.



            The last important task that our table model has to perform is to
            build a JScrollPane that knows how to work
            properly with our table. This is implemented in the
            createPagingScrollPaneForTable( ) method. This
            method starts by getting a JScrollPane and then
            modifying it to work appropriately. The modifications are really
            quite simple. We create a pair of buttons to control the paging (the
            icons for the buttons are implemented by the rather simple
            ArrowIcon class, which we haven't
            shown); we wire the buttons to the pageUp( ) and
            pageDown( ) methods of our table model; and we
            include some logic to disable buttons when we reach the top or bottom
            of the table. Finally, we turn on the scrollpane's
            scrollbars and add the buttons in the upper- and lower-right corners.
            Remember that if the scrollbars aren't enabled,
            there won't be any place to put the buttons.



            Our table is currently static: it displays but cannot update data.
            How would you implement table updates? We'll leave
            this as a thought experiment. There's some simple
            bookkeeping that you'd have to do, but the most
            interesting part would be implementing setValueAt( ) in the PagingModel class. Like
            getValueAt( ), it would have to translate between
            logical rows in the data and physical rows in the
            JTable. It would have to call
            fireTableDataChanged( ) to generate a table model
            event and cause the JTable to update the display.
            But you would also need a way to set the value of the cells that are
            not visible. For real applications, you might consider writing your
            own getRealValueAt( ) and setRealValueAt( ) that do not map incoming row values.



            Here's the very simple Record
            class; it just provides column names and generates meaningless data,
            one record (row) at a time:



            // Record.java
            // A simple data structure for use with the PagingModel demo
            //
            public class Record {
            static String[] headers = { "Record Number", "Batch Number", "Reserved" };
            static int counter;
            String[] data;

            public Record( ) {
            data = new String[] { "" + (counter++), "" + System.currentTimeMillis( ),
            "Reserved" };
            }

            public String getValueAt(int i) { return data[i]; }

            public static String getColumnName(int i) { return headers[i]; }
            public static int getColumnCount( ) { return headers.length; }
            }


            Here's the application that brings up the
            JTable using our paging model:



            // PagingTester.java
            //
            import java.awt.*;
            import java.awt.event.*;
            import javax.swing.*;
            import javax.swing.table.*;

            public class PagingTester extends JFrame {

            public PagingTester( ) {
            super("Paged JTable Test");
            setSize(300, 200);
            setDefaultCloseOperation(EXIT_ON_CLOSE);

            PagingModel pm = new PagingModel( );
            JTable jt = new JTable(pm);

            // Use our own custom scrollpane.
            JScrollPane jsp = PagingModel.createPagingScrollPaneForTable(jt);
            getContentPane( ).add(jsp, BorderLayout.CENTER);
            }

            public static void main(String args[]) {
            PagingTester pt = new PagingTester( );
            pt.setVisible(true);
            }
            }


            We just create an instance of our PagingModel to
            hold the data and construct a JTable with that
            model. Then we get a paging scrollpane from the
            JTable and add that scrollpane to the content pane
            of a JFrame.









              I l@ve RuBoard