Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-visual-mysql-database-design-mysql-workbench
Packt
21 Oct 2009
3 min read
Save for later

Visual MySQL Database Design in MySQL Workbench

Packt
21 Oct 2009
3 min read
MySQL Workbench is a visual database design tool recently released by MySQL AB. The tool is specifically for designing MySQL database. What you build in MySQL Workbench is called physical data model. A physical data model is a data model for a specific RDBMS product; the model in this article will have some MySQL unique specifications. We can generate (forward-engineer) the database objects from its physical model, which in addition to tables and their columns, can also include other objects such as view. MySQL Workbench has many functions and features; this article by Djoni Darmawikarta shows some of them by way of an example. We’ll build a physical data model for an order system where an order can be a sale order or a purchase order; and then, forward-engineer our model into an MySQL database. The physical model of our example in EER diagram will look like in the following MySQL Workbench screenshot. Creating ORDER Schema Let’s first create a schema where we want to store our order physical model. Click the + button (circled in red). Change the new schema’s default name to ORDER. Notice that when you’re typing in the schema name, its tab name on the Physical Schemata also changes accordingly—a nice feature. The order schema is added to the Catalog (I circled the order schema and its objects in red). Close the schema window. Confirm to rename the schema when prompted. Creating Order Tables We’ll now create three tables that model the order: ORDER table and its two subtype tables: SALES_ORDER and PURCHASE_ORDER, in the ORDER schema. First of all, make sure you select the ORDER schema tab, so that the tables we’ll create will be in this schema. We’ll create our tables as EER diagram (EER = Enhanced Entity Relationship). So, double-click the Add Diagram button. Select (click) the Table icon, and then move your mouse onto the EER Diagram canvas and click on the location you want to place the first table. Repeat for the other two tables. You can move around the tables by dragging and dropping. Next, we’ll work on table1, which we’ll do so using the Workbench’s table editor. We start the table editor by right-clicking the table1 and selecting Edit Table. Next, we’ll work on table1, which we’ll do so using the Workbench’s table editor. We start the table editor by right-clicking the table1 and selecting Edit Table. Rename the table by typing in ORDER over table1. We’ll next add its columns, so select the Columns tab. Replace idORDER column name with ORDER_NO. Select INT as the data type from the drop-down list. We’d like this ORDER_NO column to be valued incrementally by MySQL database, so we specify it as AI column (Auto Increment). AI is a specific feature of MySQL database. You can also specify other physical attributes of the table, such as its Collation; as well as other advanced options, such as its trigger and partioning (the Trigger and Partioning tabs). Notice that on the diagram our table1 has changed to ORDER, and it has its first column, ORDER_NO. In the Catalog you can also see the three tables. The black dots on the right of the tables indicate that they’ve been included in an diagram.  
Read more
  • 0
  • 0
  • 13050

article-image-integrating-zimbra-collaboration-suite-microsoft-outlook
Packt
21 Oct 2009
11 min read
Save for later

Integrating Zimbra Collaboration Suite with Microsoft Outlook

Packt
21 Oct 2009
11 min read
Introduction Let's face it, in today's business environment, there is only one email client that truly matters. I am not saying it is the best client, or that it offers more features, and I certainly am not saying it is the most secure. What I am saying is that you would be hard pressed to walk into an organization, of let's say more than 10 desktops, and not see users checking their email with Microsoft Outlook. Zimbra Collaboration Suite offers uncanny support for Outlook including: Native Sync with MAPI Support for both Online and Offline Modes Cached mode operation Support for multiple calendars Here, we will discuss these features and focus on configuring Outlook to work with the Zimbra server. As you will see with a Zimbra back end and an Outlook client, it is transparent to your users whether you are using Microsoft Exchange or Zimbra Collaboration Suite as your back end product. This transparency to users makes the migration from Exchange to Zimbra that much easier in the eyes of your users, especially when it comes to user training. The ability to seamlessly integrate Zimbra and Outlook is one of Zimbra's strongest assets and one of its strongest arguments for making the transition from Exchange to Zimbra. However, if you want to use the full power of Zimbra (not only the fancy look but great features such as the searches), you should use the Web Client. We will take a detailed look at Zimbra integration with Outlook, including: The Zimbra Connector for Outlook (ZCO) A look at Zimbra integration Sharing Outlook folders Outlook uses the Messaging Application Programming Interface (MAPI) to allow programs to communicate with messaging systems and stores. MAPI is proprietary to Microsoft and is key to Zimbra being able to synchronize and work with Outlook. Zimbra uses a connector to facilitate this communication—called the Zimbra Connector—for Outlook. The PST Import Wizard One of the beauties of Outlook's integration in Zimbra is that you won't start from scratch: Zimbra gives you tools that are able to import your data (emails, calendars, contacts, etc) either from a concurrent solution's server (Exchange or Domino) or directly from a PST file (the file used by Outlook to store all its data).   We'll have a look at the PST Import Wizard. To download it: Log in to the Administration Console at https://zimbra.emailcs.com:7071/. Click on the Downloads tab on the left of the navigation pane. 3. In the Content Pane, click on the PST Import Wizard to download the executable file. 4. Save the file to the local computer, or a network accessible shared folder. 5. Double click the .exe file to launch the wizard (there's no installation process). 6. Click on Next on the presentation page. 7. In the Hostname field enter: zimbra.emailcs.com. 8. In the Port field you can leave the default (80) and let the Use Secure Connection box unchecked. 9. In the Username field, enter your Zimbra's user (worker@emailcs.com) and in the Password field your Zimbra's password. Click on the Next button. You will now have to select the PST file that you want to import into the Zimbra server. The Zimbra Import Wizard helps you as it opens the default Outlook PST's directory when you click on the Browse button. Once you have selected the PST you want to import and clicked on the Open button, you can now click on the Next button of the initial window. Now, you can choose how your data will be imported: Import Junk-Mail Folder: If you leave this box checked, all your spam will be imported to the server and marked as spam on the server. Import Deleted Items Folder: With this, the deleted mails will be imported on the server. Ignore previously imported items: This option is used when you're importing your data in several attempts. If you leave it checked, the already imported mails won't be imported again. Import items received after: Checking this box and choosing a date in the calendar next to it, allows us to do a partial import based on date. Import messages with some headers but no message body: You should leave this one checked as it imports some badly formatted mails. Convert meeting, organized by me, from my old address to my new address: You need to check this box (and enter your previous email address) if you're getting a new email address on the Zimbra server. If you don't, the meetings will be imported but you won't be the owner. Migrate private appointments: This one is your own choice as Zimbra does not handle (yet) the private items; all the imported appointments will be viewable by anyone you share your calendar with.   Once your choices are made, you can click on the Next button. 14. Click OK in the confirmation window. 15. Next window will show you the import evolution (number of items and percentage). You can stop the import at anytime and start again later. Once the import is finished, a window pops up with a summary of the import session. 16. You can click on the OK button of the summary window then Finish in the last window. The Zimbra Connector for Outlook The Zimbra Connector for Outlook (ZCO) is a downloadable .msi installable file that must be installed on the desktop in order for Outlook and Zimbra to communicate. To download the ZCO to the client: Log in to the Administration Console at https://zimbra.emailcs.com:7071. Click on the Downloads tab on the left of the navigation pane. 3. In the Content Pane, click on the Zimbra Connector for Outlook to download the .msi installable file. Save the file to the local computer, or a network accessible shared folder. Double click the .msi file to start the installation process. The installation wizard will begin and go ahead and accept the License Agreement and accept all of the defaults. Once complete click FINISH. The ZCO creates a brand new profile within Outlook, called Zimbra. If you had previous profile(s) created on your computer, be sure to choose the "Zimbra" one. The ZCO is now installed, and the first time we run Outlook on this client, the connector will prompt us for configuration information. Zimbra currently supports Outlook 2003 only. In the Server Name field, enter: zimbra.emailcs.com. For port leave the default of 80. Email address will be the email address for this user. In our case, we will use the Worker Bee with an email address of worker@emailcs.com. For the password, enter the same password Worker would use to log in to the AJAX web client. Once completed, click OK and Outlook will open Worker's email box. The ZCO will now sync the Global Access List and will get all the emails from the server locally. It means that if you imported lots of item previously, you might need some time to get them back into Outlook from the server. Luckily, then the sync process happens in the background. As you can see in the following screenshot, the folders we created in the Web Client are now configured in Outlook. The first time Outlook is opened, it automatically performs a send/receive with the Zimbra server. After this initial synchronization, there is nothing a user needs to do from then on to initiate synchronization with the server. There is also nothing the user needs to set-up to let Outlook know whether or not the user is Online—connected to the server, or Offline—disconnected from the server. Outlook automatically checks the status and acts accordingly. Therefore, a user need not be connected to the server to work with email that has already been received, check the address book, or work with the Calendar. All changes that the user makes in Offline mode, will synchronize with the server the next time the server is connected and Outlook is online. At this time, we should take a quick look around Outlook and see how integrated Zimbra really is with Outlook. A Look at Zimbra Integration The integration of Zimbra is more than just the ability to send and receive email. Outlook is now acting as the front end to create contacts, appointments, and tasks that will be stored on the server. Let's take a moment to look at each one individually. Contacts The easiest way to see the integration of contacts between Outlook and Zimbra is to compose a new mail message, and instead of typing in an email address, click on the TO: button and select Global Address List from the Address Book drop-down menu. As you can see, this feature looks exactly the same whether you are using Exchange or Zimbra as your back end collaboration server. Users are familiar with this look and feel, and the ability to select users that are within the organization's Global Address List. This list comes directly from the Zimbra server and is maintained there as well. The user also has the option to select the own personal contact list. This list could be created and maintained either via the web client, through Outlook directly, or both as they will synchronize together. Appointments In most work organizations, the ability to create appointments, invite people to attend, and check invitees schedule is a key function of Exchange and Outlook. Luckily for us, the same functionality could be used with Zimbra and Outlook. As seen in the following figure, the process for creating an appointment is exactly the same. In the Calendar application, click New --> Appointment. Click on the Invite Attendees button. Click the To button and select the Global Address List from the drop-down menu. Select the CEO from the address list and click OK. Click on the Scheduling tab.   The Calendar is synced with the Zimbra server and is able to check the availability of the users within the organization, a key feature of any collaboration suite. Once you have found a schedule when all the attendees are free, go back to the Appointment tab, type in a Subject for your appointment then click on the Send button. The last feature we will look at is Sharing Outlook folders. Sharing Outlook Folders Users have the option to share any Outlook folder with users in the Global Address List. Essentially, this is the same ability we covered in an earlier chapter with the Web Client for the Contacts or Calendar. However, here the process is different. Users could be delegated different levels of access to Outlook folders. These levels include: Read View items in folder only Edit Edit any contents in the folder Create Create/add items to the folder Delete Delete/modify items in the folder Act on workflow Respond to meeting and task requests Administer Folder Modify the permissions on the folder There are also predefined roles that users could assign to other users in the Global Address List including: Administrator Has all rights to the folder listed above Delegate Has access to all rights except for Administer folder Editor Access to Read, Edit, Create and Delete Author Access to Read and Create Reviewer Read only To assign roles and rights to the folder: 1. Right click the folder and click Properties. 2. Click on the Sharing tab. 3. Click Add and select CEO from the Global Address List. 4. With CEO highlighted, select Administrator from the Permission Level drop-down-box. 5. With Administrator selected, you should be able to see all of the Permissions selected. 6. Change the Permission Level to Reviewer and you will see that only Read items, is selected. 7. Go ahead and play with the various levels so you can get a feel for the different permissions associated with the various levels. 8. Once complete, click OK. An email will be sent to the CEO informing him that he now has Administrator access to the Inbox of the Worker Bee. In order for the CEO to work with the new Shared Folder (the Worker's Inbox in this case), the CEO would simply: 1. Click on File --> Open --> Other User's Mailbox in the Outlook Menu bar. 2. Select Worker from the Global Address List. 3. Once the folder is added to Outlook, click on the Send/Receive button to synchronize the folder. Summary The goal of this article was to take a brief look at using the Microsoft Outlook client as a front end to the Zimbra Collaboration Suite. In my experience, users do not like change and they tend to be comfortable with applications they are familiar with. One of the most common objections to changing email systems is that users rely so heavily on their email and contacts that they do not want to have to learn a whole new system to access them. Hopefully, if I have done my job, you could now see how users need not be afraid of moving to a Zimbra system, because in the end, their everyday life and functionality is not going to change much. They could still use the tool that they are most familiar with, but still have the added benefit of using the AJAX Web Client when they are on the road or away from their desks.
Read more
  • 0
  • 0
  • 5411

article-image-managing-content-through-tagging-grails-part-2
Packt
21 Oct 2009
10 min read
Save for later

Managing Content through Tagging in Grails: Part 2

Packt
21 Oct 2009
10 min read
Customizing the home page in Grails With tagging in place, we can enhance the application to allow users to create their own home page. The aim is to allow users to specify the tags they are interested in, so any content with these tags will be displayed on their home page. This will allow us to break the home page up into two sections: A Most Recent section, containing the last five file uploads and messages A Your Data section, containing all the files and messages that are tagged according to the user's preferences Introducing templates Taking this approach means that files and messages will be displayed in many different places on the site, instead of just the home page. By the end of this article, messages and files will be rendered in the context of: A Most Recent section A Your Data section In the future, we will probably render messages and files in the following contexts as well: Show all files and messages Show files and messages by tags Show files and messages by search results Ideally we want to encapsulate the rendering of a file and a message so they look the same all over the site, and we don't need to duplicate our presentation logic. Grails provides a mechanism to handle this, through GSP, called templates. A template is a GSP file, just the same as our view GSP files, but is differentiated from a view by prefixing the file name with an underscore. We are going to create two templates—one template for messages, which will be called _message.gsp and the other for files, which will be called _file.gsp. The templates will be responsible for rendering a single message and a single file. Templates can be created anywhere under the views folder. The location that they are created in affects the way they are executed. To execute a template we use the grails render tag. Assume that we create our message template under the views/message folder. To render this template from a view in the same folder, we would call the following: <g:render template="message" /> However, if we need to render a message from another controller view, say the home page, which exists under views/home, we would need to call it like so: <g:render template="/message/message" /> Passing data to a template The two examples of executing a template above would only be capable of rendering static information. We have not supplied any data to the template to render. There are three ways of passing data into a template: Send a map of the data into the template to be rendered Provide an object for the template to render Provide a collection of objects for the template to render Render a map This mechanism is the same as when a controller provides a model for a view to render. The keys of the map will be the variable names that the values of the map are bound to within the template. Calling the render tag given below: <g:render template="message" model="[message: myMessage]" /> would bind the myMessage object into a message variable in the template scope and the template could perform the following: <div class="messagetitle"> <g:message code="${message.title}" encodeAs="HTML"/></div> Render an object A single object can be rendered by using the bean attribute: <g:render template="message" bean="${message}" /> The bean is bound into the template scope with the default variable named it: <div class="messagetitle"> <g:message code="${it.title}" encodeAs="HTML"/></div> Render a collection A collection of objects can be rendered by using the collection and var attributes: <g:render template="message" var="message" collection="${messages}" /> When using a collection, the render tag will iterate over the items in the collection and execute the template for each item, binding the current item into the variable name supplied by the var attribute. <div class="messagetitle"> <g:message code="${message.title}" encodeAs="HTML"/></div> Be careful to pass in the actual collection by using ${}. If just the name of the variable is passed through, then the characters in the collection variable name provided will be iterated over, rather than the items in the collection. For example, if we use the following code, the messages collection will be iterated over: <g:render template="message" var="message" collection="${messages}" /> However, if we forget to reference the messages object and just pass through the name of the object, we will end up iterating over the string "messages": <g:render template="message" var="message" collection="messages" /> Template namespace Grails 1.1 has introduced a template namespace to make rendering of templates even easier. This option only works if the GSP file that renders the template is in the same folder as the template itself. Consider the first example we saw when rendering a template and passing a Map of parameters to be rendered: <g:render template="message" model="[message: myMessage]" /> Using the template namespace, this code would be simplified as follows: <tmpl:message message="${myMessage}"/> As we can see, this is a much simpler syntax. Do remember though that this option is only available when the GSP is in the same folder as the template. Create the message and file templates Now, we must extract the presentation logic on the home page, views/home/index.gsp, to a message and file template. This will make the home page much simpler and allow us to easily create other views that can render messages and files. Create two new template files: /views/message/_message.gsp /views/file/_file.gsp Taking the code from the index page, we can fill in _message.gsp as follows: <div class="amessage"> <div class="messagetitle"> <g:message code="message.title" args="${[message.title]}" encodeAs="HTML"/> </div> <div class="tagcontainer"> <g:message code="tags.display" args="${[message.tagsAsString]}" /> </div> <div class="messagetitlesupplimentary"> <g:message code="message.user" args="${[message.user.firstName, message.user. lastName]}"/> </div> <div class="messagebody"> <g:message code="message.detail" args="${[message.detail]}" encodeAs="HTML"/> </div></div> Likewise, the <div> that contains a file panel should be moved over to the new _file.gsp. This means the main content of our home page (views/home/index.gsp) becomes much simpler: <div class="panel"> <h2>Messages</h2> <g:render template="/message/message" collection="${messages}" var="message"/></div><div class="panel"> <h2>Files</h2> <g:render template="/file/file" collection="${files}" var="file"/></div> User tags The next step is to allow users to register their interest in tags. Once we have captured this information then we can start to personalize the home page. This is going to be surprisingly simple, although it sounds like a lot! We just need to: Create a relationship between Users and Tags Create a controller to handle user profiles Create a form that will allow users to specify the tags in which they are interested User to tag relationship Creating a relationship between users and tags is very simple. Users will select a number of tags that they want to watch, but users themselves are not 'tagged', so the User class cannot extend the Taggable class. Otherwise users would be returned when performing a polymorphic query on Taggable for all objects with a certain tag. Besides allowing a user to have a number of tags, it is also necessary to be able to add tags to a user by specifying a space delimited string. We must also be able to return the list of tags as a space delimited string. The updates to the user class are: package appimport tagging.Taggerclass User { def tagService static hasMany = [watchedTags: Tagger] ... def overrideTags( String tags ) { watchedTags?.each { tag -> tag.delete() } watchedTags = [] watchedTags.addAll( tagService.createTagRelationships( tags )) } def getTagsAsString() { return ((watchedTags)?:[]).join(' ') }} User ProfileController The ProfileController is responsible for loading the current user for the MyTags form, and then saving the tags that have been entered about the user. Create a new controller class called ProfileController.groovy under the grails-app/controller/app folder, and add the following code to it: package appclass ProfileController { def userService def myTags = { return ['user': userService.getAuthenticatedUser() ] } def saveTags = { User.get(params.id)?.overrideTags( params.tags ) redirect( controller:'home' ) }} The myTags action uses userService to retrieve the details of the user making the request and returns this to the myTags view. Remember, if no view is specified, Grails will default to the view with the same name of the action. The saveTags action overrides the existing user tags with the newly submitted tags The myTags form The last step is to create the form view that will allow users to specify the tags they would like to watch. We will create a GSP view to match the myTags action in ProfileController. Create the folder grails-app/views/profile and then create a new file myTags.gsp and give it the following markup: <%@ page contentType="text/html;charset=UTF-8" %><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta name="layout" content="main"/> <title>My Tags</title></head><body><g:form action="saveTags"> <g:hiddenField name="id" value="${user.id}"/> <fieldset> <dl> <dt>My Tags</dt> <dd><g:textField name="tags" value="${user.tagsAsString}" size="35" class="bigfield"/></dd> </dl> </fieldset> <g:submitButton name="Save" value="Save"/> | <g:link controller="home">Cancel</g:link></g:form></body></html> This view will be rendered by the myTags action on the ProfileController and is provided with a User instance. The form submits the tags to the saveTags action on the ProfileController. The user id is put in a hidden field so we know which user to add the tags to when the form is submitted, and any existing tags for the user are rendered in the text field via the tagsAsString property. Add a link to the myTags action in the header navigation from our layout in main.gsp: <div id="header"> <jsec:isLoggedIn> <div id="profileActions"> <span class="signout"> <g:link controller="profile" action="myTags">My Tags</g:link> <g:link controller="auth" action="signOut">Sign out</g:link> </span> </div> </jsec:isLoggedIn> <h1><g:link controller="home">Teamwork</g:link></h1></div> Now restart the application, log in as the default user and you will be able to specify which tags you are interested in.
Read more
  • 0
  • 0
  • 1496

article-image-apache-ofbiz-service-engine-part-1
Packt
21 Oct 2009
6 min read
Save for later

Apache OFBiz Service Engine: Part 1

Packt
21 Oct 2009
6 min read
Defining a Service We first need to define a service. Our first service will be named learningFirstService. In the folder ${component:learning}, create a new folder called servicedef. In that folder, create a new file called services.xml and enter into it this: <?xml version="1.0" encoding="UTF-8" ?> <services xsi:noNamespaceSchemaLocation="http://www.ofbiz.org/dtds/services.xsd"> <description>Learning Component Services</description> <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="learningFirstService"> <description>Our First Service</description> <attribute name="firstName" type="String" mode="IN" optional="true"/> <attribute name="lastName" type="String" mode="IN" optional="true"/> </service> </services> In the file ${component:learning}ofbiz-component.xml, add after the last <entity-resource> element this: <service-resource type="model" loader="main" location="service def/services.xml"/> That tells our component learning to look for service definitions in the file ${component:learning}servicedefservices.xml. It is important to note that all service definitions are loaded at startup; therefore any changes to any of the service definition files will require a restart! Creating the Java Code for the Service In the package org.ofbiz.learning.learning, create a new class called LearningServices with one static method learningFirstService: package org.ofbiz.learning.learning; import java.util.Map; import org.ofbiz.service.DispatchContext; import org.ofbiz.service.ServiceUtil; public class LearningServices { public static final String module = LearningServices.class.getName(); public static Map learningFirstService(DispatchContext dctx, Map context){ Map resultMap = ServiceUtil.returnSuccess("You have called on service 'learningFirstService' successfully!"); return resultMap; } } Services must return a map. This map must contain at least one entry. This entry must have the key responseMessage (see org.ofbiz.service.ModelService.RESPONSE_MESSAGE), having a value of one of the following: success or ModelService.RESPOND_SUCCESS error or ModelService.RESPOND_ERROR fail or ModelService.RESPOND_FAIL By using ServiceUtil.returnSuccess() to construct the minimal return map, we do not need to bother adding the responseMessage key and value pair. Another entry that is often used is that with the key successMessage (ModelService.SUCCESS_MESSAGE). By doing ServiceUtil.returnSuccess("Some message"), we will get a return map with entry successMessage of value "Some message". Again, ServiceUtil insulates us from having to learn the convention in key names. Testing Our First Service Stop OFBiz, recompile our learning component and restart OFBiz so that the modified ofbiz-component.xml and the new services.xml can be loaded. In ${component:learning}widgetlearningLearningScreens.xml, insert a new Screen Widget: <screen name="TestFirstService"> <section> <widgets> <section> <condition><if-empty field-name="formTarget"/></condition> <actions> <set field="formTarget" value="TestFirstService"/> <set field="title" value="Testing Our First Service"/> </actions> <widgets/> </section> <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}"> <decorator-section name="body"> <include-form name="TestingServices" location="component://learning/widget/learning/LearningForms.xml"/> <label text="Full Name: ${parameters.fullName}"/> </decorator-section> </decorator-screen> </widgets> </section> </screen> In the file ${component:learning}widgetlearningLearningForms.xml, insert a new Form Widget: <form name="TestingServices" type="single" target="${formTarget}"> <field name="firstName"><text/></field> <field name="lastName"><text/></field> <field name="planetId"><text/></field> <field name="submit"><submit/></field> </form> Notice how the formTarget field is being set in the screen and used in the form. For now don't worry about the Full Name label we are setting from the screen. Our service will eventually set that. In the file ${webapp:learning}WEB-INFcontroller.xml, insert a new request map: <request-map uri="TestFirstService"> <event type="service" invoke="learningFirstService"/> <response name="success" type="view" value="TestFirstService"/> </request-map> The control servlet currently has no way of knowing how to handle an event of type service, so in controller.xml we must add a new handler element immediately under the other <handler> elements: <handler name="service" type="request" class="org.ofbiz.webapp.event.ServiceEventHandler"/> <handler name="service-multi" type="request" class="org.ofbiz.webapp.event.ServiceMultiEventHandler"/> We will cover service-multi services later. Finally add a new view map: <view-map name="TestFirstService" type="screen" page="component://learning/widget/learning/LearningScreens.xml#TestFirstService"/> Fire to webapp learning an http OFBiz request TestFirstService, and see that we have successfully invoked our first service: Service Parameters Just like Java methods, OFBiz services can have input and output parameters and just like Java methods, the parameter types must be declared. Input Parameters (IN) Our first service is defined with two parameters: <attribute name="firstName" type="String" mode="IN" optional="true"/> <attribute name="lastName" type="String" mode="IN" optional="true"/> Any parameters sent to the service by the end-user as form parameters, but not in the services list of declared input parameters, will be dropped. Other parameters are converted to a Map by the framework and passed into our static method as the second parameter. Add a new method handleInputParamaters to our LearningServices class. public static Map handleParameters(DispatchContext dctx, Map context){ String firstName = (String)context.get("firstName"); String lastName = (String)context.get("lastName"); String planetId= (String)context.get("planetId"); String message = "firstName: " + firstName + "<br/>"; message = message + "lastName: " + lastName + "<br/>"; message = message + "planetId: " + planetId; Map resultMap = ServiceUtil.returnSuccess(message); return resultMap; } We can now make our service definition invoke this method instead of the learningFirstService method by opening our services.xml file and replacing: <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="learningFirstService"> with: <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="handleParameters"> Once again shutdown, recompile, and restart OFBiz. Enter for fields First Name, Last Name, and Planet Id values Some, Name, and Earth, respectively. Submit and notice that only the first two parameters went through to the service. Parameter planetId was dropped silently as it was not declared in the service definition. Modify the service learningFirstService in the file ${component:learning}servicedefservices.xml, and add below the second parameter a third one like this: <attribute name="planetId" type="String" mode="IN" optional="true"/> Restart OFBiz and submit the same values for the three form fields, and see all three parameters go through to the service.  
Read more
  • 0
  • 0
  • 3399

article-image-facebook-application-development-ruby-rails
Packt
21 Oct 2009
4 min read
Save for later

Facebook Application Development with Ruby on Rails

Packt
21 Oct 2009
4 min read
Technologies needed for this article RFacebook RFacebook (http://rfacebook.rubyforge.org/index.html) is a Ruby interface to the Facebook APIs. There are two parts to RFacebook—the gem and the plug-in. The plug-in is a stub that calls RFacebook on the Rails library packaged in the gem. RFacebook on Rails library extends the default Rails controller, model, and view. RFacebook also provides a simple interface through an RFacebook session to call any Facebook API. RFacebook uses some meta-programming idioms in Ruby to call Facebook APIs. Indeed Indeed is a job search engine that allows users to search for jobs based on keywords and location. It includes job listings from major job boards and newspapers and even company career pages. Acquiring candidates through Facebook We will be creating a Facebook application and displaying it through Facebook. This application, when added into the list of a user's applications, allows the user to search for jobs using information in his or her Facebook profile. Facebook applications, though displayed within the Facebook interface, are actually hosted and processed somewhere else. To display it within Facebook, you need to host the application in a publicly available website and then register the application. We will go through these steps in creating the Job Board Facebook application. Creating a Rails application Next, create a Facebook application. To do this, you will need to first add a special application in your Facebook account—the Developer application. Go to http://www.facebook.com/developers and you will be asked to allow Developer to be installed in your Facebook account. Add the Developer application and agree to everything in the permissions list. You will not have any applications yet, so click on the create one link to create a new application. Next you will be asked for the name of the application you want to create. Enter a suitable name; in our case, enter 'Job Board' and you will be redirected to the Developer application main page, where you are shown your newly created application with its API key and secret. You will need the API key and secret in a while. Installing and configuring RFacebook RFacebook consists of two components—the gem and the plug-in. The gem contains the libraries needed to communicate with Facebook while the plug-in enables your Rails application to integrate with Facebook. As mentioned earlier, the plug-in is basically a stub to the gem. The gem is installed like any other gem in Ruby: $gem install rfacebook To install the plug-in go to your RAILS_ROOT folder and type in: $./script/plugin install svn://rubyforge.org/var/svn/rfacebook/trunk/rfacebook/plugins/rfacebook Next, after the gem and plug-in is installed, run a setup rake script to create the configuration file in the RAILS_ROOT folder: $rake facebook:setup This creates a facebook.yml configuration file in RAILS_ROOT/config folder. The facebook.yml file contains three environments that mirror the Rails startup environments. Open it up to configure the necessary environment with the API key and secret that you were given when you created the application in the section above. development: key: YOUR_API_KEY_HERE secret: YOUR_API_SECRET_HERE canvas_path: /yourAppName/ callback_path: /path/to/your/callback/ tunnel: username: yourLoginName host: www.yourexternaldomain.com port: 1234 local_port: 5678 For now, just fill in the API key and secret. In a later section when we configure the rest of the Facebook application, we will need to revisit this configuration. Extracting the Facebook user profile Next we want to extract the user's Facebook user profile and display it on the Facebook application. We do this to let the user confirm that this is the information he or she wants to send as search parameters. To do this, create a controller named search_controller.rb in the RAILS_ROOT/app/controllers folder. class SearchController < ApplicationController before_filter :require_facebook_install layout 'main' def index view render :action => :view end def view if fbsession.is_valid? response = fbsession.users_getInfo(:uids => [fbsession.session_user_id], :fields => ["current_location", "education_history", "work_history"]) @work_history = response.work_history @education_history = response.education_history @current_location = response.current_location endend
Read more
  • 0
  • 0
  • 3936

article-image-software-documentation-trac
Packt
21 Oct 2009
4 min read
Save for later

Software Documentation with Trac

Packt
21 Oct 2009
4 min read
Documentation—if there is one word that installs fear in most developers, it must be this one. No one in their right mind would argue the value of documentation, but it is the actual act of writing it that concerns developers so. The secret of creating good documentation is to make the process of doing so as painless as possible, and if we are lucky maybe even attractive, to the developers. The only practical way to achieve that is to reduce friction. The last thing we need when we are in middle of fixing a bug is to wrestle with our word processor, or even worse try to find the right document to update. What's in a name?Throughout the rest of this article, we will refer to various URLs that point to specific areas of our Trac environment, Subversion repository, or WebDAV folders. Whenever you see servername, replace it with your own server name. Making Documentation Easy One of the reasons Trac works so well for managing software development is because it is browser based. Apart from our development environment, the browser, along with our email client, are the next most likely applications we are going to have installed and running on our computer. If access to our Trac environment is only a click away, it stands to reason that we are more likely to use it. We can refer to Trac as a "wiki on steroids" because of the way the developers have integrated the typical features of a wiki throughout the whole product. However, for all the extra features and integration, at its heart Trac is basically just a wiki and this is the main reason why it so useful in helping smooth the documentation process. A wiki is a web application that allows visitors to create and modify its content. Let's expand on that slightly. As well as letting us view content—like a normal website—a wiki lets us create or edit the content as we desire. This could take the form of creating new content, or simply touching up the spelling on something that already exists. While the general idea with a wiki is that anyone can edit them, in practice this can lead to abuse, vandalism, or spam. The obvious solution to this is to involve people to authenticate the edit. Do we really need this security?Yes. Having these security requirements provides us with accountability. We will always be able to see when something is done, but by enforcing security we can see who did it. While this does cause some administrative overhead to create and maintain authentication details for anyone involved with our development projects, the benefits outweigh the costs. Accessing Trac Before we look at how to modify and create pages, let's see how our Trac environment looks to a normal (i.e. unauthenticated) user. To do this we need to open our web browser and enter the URL http://servername/projects/sandbox into the address bar and then press the Enter key. This will take us to the default page (which is actually called WikiStart). When we access our project as an unauthenticated (or anonymous in Trac parlance) user, the majority of it will look and act like a normal website and the wiki in particular seems just like the usual collection of interlinked pages. However, as soon as we authenticate ourselves to Apache (which passes that information on to Trac), it all changes. If we click the Login link in the top right of the page now, we will be presented with our browser's usual authentication dialog box as shown in the following screenshot. Input the proper username and password and click OK. If we enter them correctly we will be taken back to the same page, but this time there will be two differences. Firstly, instead of the login link we will see the text logged in as followed by the username we used and a Logout link. Secondly, if we scroll to the bottom of the page there are some buttons that allow us to modify the page in various ways. Anonymous users have permission to only view wiki pages, while authenticated users have full control. We should try that out now—click the Logout link and scroll down again, and you will see that the buttons are absent.
Read more
  • 0
  • 0
  • 4971
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-installing-drupal-themes
Packt
21 Oct 2009
5 min read
Save for later

Installing Drupal Themes

Packt
21 Oct 2009
5 min read
The large and active community of developers that has formed around Drupal guarantees a steady flow of themes for this popular CMS. The diversity of that community also assures that there will be a wide variety of themes produced. Add into the equation the existence of a growing number of commercial and open source web designs and you can be certain that somewhere out there is a design that is close to what you want. The issue becomes identifying the sources of themes and designs, and determining how much work you want to do yourself. You can find both design ideas and complete themes on the Web. You need to decide whether you want to work with an existing theme, or convert a design into a theme, or whether you want to start from scratch, unburdened by any preliminary constraints or alien code. For purposes of this article, we will be dealing with finding, installing, and then uninstalling an existing and current Drupal theme. This article assumes you have a working Drupal installation, and that you have access to the files on your server. Finding Additional Themes There are several factors to consider when determining the suitability of an existing theme. The first issue is compatibility. Due to changes made to Drupal in the 5.x series, older themes will not work properly with Drupal 5.x. Accordingly, your first step is to determine which version of Drupal you are running. To find the version information for your installation, go to Administer | Logs | Status Report. The first line of the Status Report tabular data will show your version number. If you do not see the Status Report option, then you are probably using a Drupal version earlier than 5.x. We suggest you upgrade as this book is for Drupal 5.x. If you know your Drupal version, you can confirm whether the theme you are considering is usable on your system. If the theme you are looking at doesn't provide versioning information, assume the worst and make sure you back up your site before you install the questionable theme. Once you're past the compatibility hurdle, your next concern is system requirements; does the theme require any additional extensions to work properly? Some themes are ready to run with no additional extensions required. Many themes require that your Drupal installation include a particular templating engine. The most commonly required templating engine is PHPTemplate. If you are running a recent instance of Drupal, you will find that the PHPTemplate engine is installed by default. You can also download a variety of other popular templating engines, including Smarty and PHPTal from http://drupal.org/project/Theme+engines.Check carefully whether the theme you've chosen requires you to download and install other extensions. If so, track down the additional extensions and install them first, before you install your theme. A good place to start looking for a complete Drupal theme is, perhaps not surprisingly, the official Drupal site. At Drupal.org, you can find a variety of downloads, including both themes and template engines. Go to http://drupal.org/project/Themes to find a listing of the current collection of themes. All the themes state very clearly the version compatibility and whether there are any prerequisites to run the theme. In addition to the resources on the official Drupal site, there is an assortment of fan sites providing themes. Some sites are open source, others commercial, and a fair number are running unusual licenses (most frequently asking that footers be left intact with links back to their sites). Some of the themes available are great; most are average. If your firm is brand sensitive, or your design idiosyncratic, you will probably find yourself working from scratch. Regardless of your particular needs, the theme repositories are a good place to start gathering ideas. Even if you cannot find exactly what you need, you sometimes find something with which you can work. An existing set of properly formed theme files can jump start your efforts and save you a ton of time. If you wish to use an existing theme, pay attention to the terms of usage. You can save yourself (or your clients) major headaches by catching any unusual licensing provisions early in the process. There's nothing worse than spending hours on a theme only to discover its use is somehow restricted. One source for designs with livable usage policies is the Open Source Web Design site, http://www.oswd.org, which includes a repository of designs, all governed by open source licensing terms. The down side of this resource is that all you get is the design—not the code, not a ready-made theme. You will need to convert the design into a usable theme. For this article, let's search out a completed theme and for the sake of simplicity, let's take one from the official Drupal site. I am going to download the Gagarin theme from Drupal.org. I'll refer to this theme as a working example of some ofthe steps below. You can either grab a copy of the same theme or you can use another—the principles are the same regardless. Gagarin is an elegant little theme from Garamond of the Russian Drupal community. Gagarin is set up for a two-column site (though it can be run in three columns) and works particularly well for a blog site.
Read more
  • 0
  • 0
  • 2836

article-image-email-languages-and-jfile-joomla
Packt
21 Oct 2009
13 min read
Save for later

Email, Languages, and JFile with Joomla!

Packt
21 Oct 2009
13 min read
Sending emails Joomla!'s core content management has a built-in feature where visitors are able to send articles to their friends through email. A similar feature can be added to the "Restaurant Reviews" component. The component can be modified to display a link to a form where the email address of a friend can be entered along with a short message. We will create a new view to handle this form. Go to the /components/com_restaurants/views folder of your Joomla! component and create a new folder named email. In this folder, create a file called view.html.php, and load it with the following code: <?phpdefined( '_JEXEC' ) or die( 'Restricted access' );jimport( 'joomla.application.component.view');JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . DS . 'tables');class RestaurantsViewEmail extends JView{ function display($tpl = null) { $id = JRequest::getInt('id', 0); $review =& JTable::getInstance('review', 'Table'); $review->load($id); $this->assignRef('review', $review); parent::display($tpl); }} This code first checks to make sure that the file is not being called directly, loads in the framework code for views, and adds /administrator/components/com_restaurants/tables to the include path list of JTable. After declaring RestaurantsViewEmail as an extension of JView, the display() function pulls in the restaurant review ID from the request. The getInstance() member function of JTable is used to get a reference to a table object for reviews. The review matching the ID is then loaded and assigned to the template using the assignRef() member function. Finally, JView's original display() member function is called. Although the code in view.html.php now loads the review that our visitors are trying to email, the form still needs to be added. Create a folder named tmpl in the existing /components/com_restaurants/views/email folder, and create a new file default.php inside it with the following code: <?php defined( '_JEXEC' ) or die( 'Restricted access' ); ?><form action="index.php" method="post"> <div class="contentheading">Email review</div> <p>&nbsp;</p> <p>Fill this form to send this review of <em> <?php echo htmlspecialchars($this->review->name) ?> </em> to someone you know who will find it useful:</p> <div> <strong>Your name:</strong> </div> <p> <input type="text" name="sender_name" value="" /> </p> <div> <strong>Your email address:</strong> </div> <p> <input type="text" name="sender_email" value="" /> </p> <div><strong>Recipient's email address:</strong></div> <p> <input type="text" name="recipient" value="" /> </p> <div><strong>Message:</strong></div> <p> <textarea name="message" rows="4" cols="40"></textarea> </p> <p> <input type="submit" value="Send Review" class="button" /> </p> <?php echo JHTML::_( 'form.token' ); ?> <input type="hidden" name="id" value= "<?php echo $this->review->id; ?>" /> <input type="hidden" name="task" value="sendemail" /> <input type="hidden" name="option" value= "<?php echo $option; ?>" /></form> Before any output occurs, the code checks to make sure that the request is coming from within Joomla! and is not being called directly. The file then outputs a brief message identifying the review by name, so that the visitors are sure of what they are sending. The form then continues with fields for the visitor's name and email address, the email address of their friend, and an optional message. Just after the submit button, there is a series of hidden fields. First, JHTML::_('form.token') is called to generate a token for the request. This is the same style of token as is used in the backend to thwart CSRF attacks, only here it is used to cut down on abuse. Next, the ID of the review being emailed is placed into the form. The task variable is set to sendemail, which is a function that we will add to the controller in a moment. Finally, option is set, so that Joomla! loads the com_restaurants component. Linking the form If you now load index.php?option=com_restaurants&view=email in your browser, you will see this screen: The message at the top of the screen is incomplete as we simply loaded the view without a review id. Although we could add id as a parameter onto the end of the URL, our visitors will not be doing this. They will need a link to follow from the review itself. To add this link, we need to make some small adjustments to the single view. This view first needs to generate URLs to the email view with the ID already included. Do this by making the following highlighted adjustment to the display() function in /components/com_restaurants/views/single/view.html.php: $date = JHTML::Date($review->review_date);$backlink = JRoute::_('index.php?option=com_restaurants');$emaillink = JRoute::_('index.php?option=com_restaurants&view=email&id=' . $id);$user =& JFactory::getUser();$comments =& $this->get('Comments');$this->assign('display_comments', $params->get('display_comments', '1'));$this->assignRef('review', $review);$this->assignRef('smoking', $smoking);$this->assignRef('date', $date);$this->assignRef('backlink', $backlink);$this->assignRef('emaillink', $emaillink);$this->assignRef('name', $user->name);$this->assignRef('comments', $comments);parent::display($tpl); With a URL to the email view now being generated, we now need to display it. Open /components/com_restaurants/views/single/tmpl/default.php and add the following highlighted code: <p><?php echo htmlspecialchars($this->review->review); ?></p><p><em>Notes:</em> <?php echo htmlspecialchars($this->review->notes); ?></p><p><a href="<?php echo htmlspecialchars($this->emaillink); ?>">Email this to a friend</a></p><a href="<?php echo htmlspecialchars($this->backlink); ?>">&lt; return to the reviews</a> After saving the files, navigate to one of the restaurant reviews in the frontend. Your screen should now have an Email this to a friend link, like the following screenshot: When you click on the Email this to a friend link, you will get a screen that looks like the following: Sending email With the form and the navigation in place, we can now focus on creating the function that creates the email and sends it to the correct place. Throughout the creation of this component, we have used member functions of JRequest to filter our input. We will do the same here, but go one step further by verifying that the mail addresses entered are valid. This extra step is necessary as malicious users can otherwise add invalid newline characters to your email fi elds, taking control of the message sending process. Once a remote user has control, the message can be sent anywhere with any text. This is known as an "Email Header Injection attack". If you fail to protect your website against this type of attack, your component could be hijacked and used to send thousands of spam messages without your knowledge. With this caution in mind, we will write the sendemail() function to process the form and send the review. Open /components/com_restaurants/restaurants.php and add this function to the controller class: function sendemail(){ JRequest::checkToken() or jexit( 'Invalid Token' ); JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . DS . 'tables'); $sender_email = JRequest::getString('sender_email', ''); $recipient = JRequest::getString('recipient', ''); $sender_name = JRequest::getString('sender_name', ''); $message = JRequest::getString('message', ''); $id = JRequest::getInt('id', 0); jimport( 'joomla.mail.helper' ); if (!JMailHelper::isEmailAddress($sender_email) || !JMailHelper::isEmailAddress($recipient)) { JError::raiseError(500, 'One of the emails you entered is invalid. Please try again.'); } $review =& JTable::getInstance('review', 'Table'); $review->load($id); $link = JURI::base() . 'index.php?option=com_restaurants&view= single&id=' . $id; $subject = $sender_name . ' wants you to know about ' . $review->name; $body = "Here's a review of {$review->name}:nn"; $body .= "{$review->review}nn"; if ($message != '') { $body .= $sender_name . " also added this message:n"; $body .= '"' . $message . '"' . "nn"; } $body .= "For all of the details, follow this link: {$link}"; $sender_name = JMailHelper::cleanAddress($sender_name); $subject = JMailHelper::cleanSubject($subject); $body = JMailHelper::cleanBody($body); if (JUtility::sendMail($sender_email, $sender_name, $recipient, $subject, $body) !== true) { JError::raiseNotice( 500, 'Email failed.' ); } JRequest::setVar('view', 'email'); JRequest::setVar('layout', 'success'); $this->display();} Before even checking the variables, the checkToken() member function of JRequest is called to make sure that the user actually loaded the form. Although this will not prevent spammers from abusing your component, it will slow them down; they will need to load your form and extract the token for each message. Next, the path /administrator/components/com_restaurants/tables is added to the list of paths JTable will use to find table classes. This is necessary because we will be loading the review in a moment, in order to extract the summary and title. The email address of the sender, the address of the recipient, the name of the sender,any added message, and the review's ID are all extracted from the HTTP request.With the exception of the id field, all fields are filtered as strings. The id field is more stringently filtered to ensure that the value is also an integer. Joomla! has a library for handling email data, which we pull in by calling jimport( 'joomla.mail.helper' );. This is used immediately to ensure that the entered email addresses are in a valid format. Both the sender's address and the recipient's address are tested. If either one is in an invalid format or contains newlines, the raiseError() member function of JError is used to stop the script and display a message. The function continues by generating some review-specific data. The review is loaded from the database, and then a link back to the review is built using the review's ID. A subject line is built with the sender's name and the name of the restaurant. The body of the email starts with the name of the review, followed by the review itself. If the visitor added a personal message then this is added, along with their name. The link to the full review is added at the end. With all of the content generated, there is one step left before sending the message. The formats of the email addresses have already been validated, but the sender's name, subject, and body all contain user-supplied data. These must be filtered before they are sent off. The cleanAddress(), cleanSubject(), and cleanBody() member functions of JMailHelper strip out any attempts at email header injections. Finally, the sendMail() member function of JUtility is called to send the email with the sender's address, sender's name, recipient's email address, subject line, and body as the respective parameters. If this function fails for any reason, the raiseError() member function of JError is called and processing stops. Adding a success message When you perform an action that sends an email, most web applications will display an "email success" screen letting you know that the message went through. Our component will be no different. At the end of the sendemail() function, we set the view request variable to email, set the layout request variable to success, and then call the display() member function that defaults to JView::display(). Why aren't we calling $this->setRedirect()?Typically, $this->setRedirect() would be called to tell the controller to redirect the user to a specific page. This time, we have chosen to instead set the request variables and call the display() function directly. This prevents Joomla! from sending a redirect HTTP header to the browser, which ultimately saves another trip to the server. Because we want to display a message instead of going back to the review straight away, this makes sense. It may also be useful in cases where you have a client-side application that would otherwise be confused by a redirect. Instead of creating an entirely separate view to handle the success screen, we have opted instead to set the layout request variable and point back to the email view. This helps us to cut down on the number of views required, and allows us to reuse some of the view code. To add the markup for the success screen, we need to create a new file called success.php to the tmpl folder of the email view. Enter the code below in success.php: <?php defined( '_JEXEC' ) or die( 'Restricted access' ); ?><div class="componentheading">Success!</div><p>The review for <?php echo htmlspecialchars($this->review->name) ?> has been successfully emailed.</p><p><a href="<?php echo htmlspecialchars($this->reviewlink) ?>">Return to the review for <?php echo htmlspecialchars($this->review->name) ?>.</a></p> After checking to make sure that the request to success.php is coming from within Joomla!, a confirmation message, including the name, of the review is displayed. A link back to the review is also output. However, the URL for this link has not yet been generated. To do this, go to /components/com_restaurants/views/email/view.html.php and add the highlighted code to the display() function: $review->load($id);$reviewlink = JRoute::_('index.php?option=com_restaurants&view= single&id=' . $id);$this->assignRef('review', $review);$this->assign('reviewlink', $reviewlink);parent::display($tpl); Save all of your code, then load one of the reviews and click on the Email this to a friend link. Fill the form and click the Send Review button. If the email goes through correctly, you should see a screen like the following: If you sent the review to yourself, the email should look similar to the following: Here's a review of The Daily Dish: Chicken fried steak, meatloaf, potatoes, string beans and hot turkey sandwiches are all favorites from this venerable institution the locals swear by. Apple, pumpkin, and pecan pies round out the dessert selection.Dinner there won't break the bank, either. Ralph Elderman also added this message:"You should really try this place sometime. I take the family there every week!" For all of the details, follow this link: http://localhost/index.php?option=com_restaurants&view=single&id=2
Read more
  • 0
  • 0
  • 4833

article-image-customizing-plugins-joomla-15x-part-1
Packt
21 Oct 2009
9 min read
Save for later

Customizing Plugins in Joomla! 1.5x (Part 1)

Packt
21 Oct 2009
9 min read
The code used in this article can be downloaded from here. Plugin composition and operation     Like a module, in its simplest form, a plugin can consist of only two files, a PHP file with the actual code for the plugin, and an XML manifest that tells Joomla! what to do with the plugin. Despite this apparent simplicity, plugins are very powerful, and more difficult to understand than modules and components. Plugins are designed to run at certain times during the execution of our site, and they perform actions that can only be done at these times. For example, in our sample site we want to hide some of our content from guests, and only show it to paid subscribers. This action can only be performed when we are actually preparing the content to be displayed, because we need to wait until we identify if the viewer is a guest or subscriber, and then make the changes to the content dynamically. In a different example, checking if a subscriber's subscription is valid is something that only needs to be done when they try to login, and not on every page load. Plugin types Plugins are divided into eight types, as follows: Authentication Content Editors Editors-XTD Search System User XML-RPC Authentication Authentication plugins are designed to allow the site to check the user's authentication against a variety of sources. The default is to check the user's authentication against a username and password stored in the Joomla! database, which, as of Joomla! 1.5, will be the username and password fields in the #__user table (#__ is the table prefix we chose when setting up Joomla!). However, any source with a public API can be used to verify someone's authentication details. Common uses are LDAP, OpenID, a Google account, a subscription, community component, and more. On our site, for example, we are already using an authentication plugin to verify the subscriptions of users when they attempt to login. Content Possibly the most commonly used of all plugins, content plugins allow content items to be modified or have additional features added to them. We could, for example, use content plugins to cloak email addresses, embed audio or video into our pages, or do text replacements. We can even embed components and modules into our pages via plugins. We will later look at a content plugin that we will use to hide and show content depending on a user's subscription. Editors Editors plugins add WYSIWYG editors that we can use when editing our content. We installed JCE on our site earlier, which is the most popular Joomla! editor plugin as of this publication according to Joomla.org. Editors-XTD Editors-XTD (extended) plugins allow us to add additional buttons to the editors. The Image, Read more, and Pagebreak buttons on the default Joomla! WYSIWYG editor, for example, are actually plugins. Search Search plugins allow us to search through the data from different components. By default, Joomla! comes with plugins that search through content articles and the Contacts and Weblinks components. These can be expanded upon by creating or installing search plugins for other extensions. System System plugins are arguably the most powerful and most flexible types of plugins for Joomla!, as they can execute at several different pre-defined points during the execution of a Joomla! page plugin. They can be used to perform a vast array of functions, such as loading extra scripts or CSS into the header of a web page, redirecting people away from pages, logging statistics, and more. User User plugins allow us to perform actions at different times with respect to users. Such times include logging in and out, and also when saving changes to a user's profile. User plugins are often used to create a "bridge" between Joomla! and other web applications (such as the phpBB forum or the osCommerce e-commerce platform.). XML-RPC XML-RPC plugins are for communicating between our Joomla! site and other external applications, such as a desktop application or a different web site. Plugin events As a Joomla! site loads a page, it steps through a series of events as part of that process. The events it steps through are determined by the type of page it is loading. Plugins are always tied to one or more of these events, and are executed during those events as required. When loading a page of content, for example, we would step through a mix of the system and some of the content events. When loading the same page for editing, we will step through the system events, different content events, and also possibly editor events. The events triggered in Joomla! are: Authentication onAuthenticate Content onPrepareContent onAfterDisplayTitle onBeforeDisplayContent onBeforeContentSave onAfterContentSave Editors onInit onGetContent onSetContent onSave onDisplay onGetInsertMethod Editors XTD (Extended) onDisplay Search onSearch onSearchAreas System onAfterInitialise onAfterRoute onAfterDispatch onAfterRender User onLoginUsexr onLoginFailure onLogoutUser onLogoutFailure onBeforeStoreUser onAfterStoreUser onBeforeDeleteUser onAfterDeleteUser XML-RPC onGetWebServices Most of these events are easy to understand from their name, but just in case, more information can be found on the Joomla! documentation wiki at http://docs.joomla.org/CategoryPlugins. Some events are only activated at specific times, such as onAuthenticate, which is only activated when someone logs into their account. Others are activated on every page load. Content events are activated on all content pages and only on content pages, not on pages with components other than com_content. Content plugins are also only executed on the main body content itself and don't have access to the template or other module data. So a text replacement content plugin, for example, wouldn't change any text in modules or the template, only in the main content itself. It is actually possible for modules and components to manually activate plugin events with clever programming, but this is not the default Joomla! behavior. It is usually done when a developer wants to apply content plugin restrictions/changes to a module. Plugin order Aside from the events and types, there is a third important factor to consider when setting up our plugins. That is the order in which the plugins of a particular type are executed. This order is best observed on the Plugin Manager screen that can be found under the Extensions menu. The order in which the plugins execute is something not many people think about, but is really quite powerful and useful. This is because the plugins which execute later, can then use the output or effects of the earlier executing plugins as input. For example, imagine we have a plugin that displays different text for different user types, and we have another plugin that reads certain text values and replaces them with embedded video or audio. If we wanted to be able to show different videos to different groups, then we could use the first plugin to generate the different command strings for the second plugin, and have it generate them based on the user type. The second plugin, our media embedding plugin, doesn't even know that the first plugin exists. All it knows is which videos it needs to display based on what is in the content item. If the media plugin executes first, then it will generate both videos regardless of the user type. As another example, imagine we have some sort of external application and we log users into it after they authenticate via an authentication plugin. We need to make sure that this plugin is executed after all of our other authentication plugins that may check a user's credentials or account status. Otherwise, someone may get logged into our external application even though they were prevented from login into our Joomla! site. So a hacker, for example, could get access to our external application without needing to even successfully get into our main site. This was all because we had the order of our plugins wrong. So when we install and activate plugins, it is well worth taking the time to double check that everything happens in the order it is meant to be in. If one of our plugins is not behaving how it should, it might be worth checking the order to see if another plugin is conflicting with it. Customizing a Plugin Now that we have a better understanding of how our plugins work and fit together, we are going to try our hand at customizing one for our site. This will hopefully give us the understanding and confidence to make any other customizations we need in the future. As with modules, it is often easier to find a plugin that does most of what we want it to do and then make changes to it so that it meets our needs more completely. Looking back over our goals, one that requires a plugin is that we want to limit access to certain parts of our content to only our paying subscribers. This effect is going to be best achieved via content plugin, so we chose the Ninja Access plugin to fill this need. To use Ninja Access we first need to mark the content we want to restrict with special tags and indicate the user groups we want to see what is contained within the tags. When the page is produced, the plugin reads the visitor's user group and then compares it to the ones in the list provided by the tag. If the user groups match, then the content is displayed, if not, then it is hidden. For example: {njaccess 0}shows only to guest users{/njaccess}{njaccess 18,19,20,21,23,24,25}shows to all users who are not a guest{/njaccess} The numbers in the examples above indicate the default Joomla! user group ids. The most important ones are: 0 = Guests 18 = Registered 24 = Administrators 25 = Super Administrators We could use this as it is, but as we don't have a component installed to create new access groups, it won't be very flexible. We could get into trouble in the future if we decide to let people register without getting a subscription, or create a free subscription. In this instance, we will have paying and free subscribers all in the number 18 user group. Also, as we are always going to be restricting the same groups, we don't really need to type the parameters in every single time. Making our plugins always restrict the same groups automatically will save us some time and reduce mistakes. Lastly, do we really need to type njaccess every time? Let's shorten it to something like soc—subscriber only content. For our first dilemma, a better idea than groups might be to associate the access to certain AEC subscriptions that are currently active. That way if people's subscriptions expire, or they get a free account, the content is still properly controlled regardless of their user groups.
Read more
  • 0
  • 0
  • 2042

article-image-access-control-php5-cms-part-1
Packt
21 Oct 2009
12 min read
Save for later

Access Control in PHP5 CMS - Part 1

Packt
21 Oct 2009
12 min read
The Problem We need to design and implement a role-based access control (RBAC) system, demonstrate its use, and ensure that the system can provide: a simple data structure a flexible code to provide a usable RBAC interface efficiency so that RBAC avoids heavy overheads Discussion and Considerations Computer systems have long needed controls on access. Early software commonly fell into the category that became known as access control lists (ACL). But these were typically applied at a fairly low level in systems, and referred to basic computer operations. Further development brought software designed to tackle more general issues, such as control of confidential documents. Much work was done on discretionary access control (DAC), and mandatory access control (MAC). A good deal of academic research has been devoted to the whole question of access controls. The culmination of this work is that the model most widely favored is the role-based access control system, such a mouthful that the acronym RBAC is used hereafter. Now although the academic analysis can be abstruse, we need a practical solution to the problem of managing access to services on a website. Fortunately, rather like the relational database, the concepts of RBAC are simple enough. RBAC involves some basic entities. Unfortunately, terminologies are not always consistent, so let us keep close to the mainstream, and define some that will be used to implement our solution: Subject: A subject is something that is controlled. It could be a whole web page, but might well be something much more specific such as a folder in a file repository system. This example points to the fact that a subject can often be split into two elements, a type, and an identifier. So the folders of a file repository count as a type of subject, and each individual folder has some kind of identifier. Action: An action arises because we typically need to do more than simply allow or deny access to RBAC subjects. In our example, we may place different restrictions on uploading files to a folder and downloading files from the folder. So our actions might therefore include 'upload', and 'download'. Accessor: The simplest example of an accessor is a user. The accessor is someone or something who wants to perform an action. It is unduly restrictive to assume that accessors are always users. We might want to consider other computer systems as accessors, or an accessor might be a particular piece of software. Accessors are like subjects in splitting into two parts. The first part is the kind of accessor, with website users being the most common kind. The second part is an identifier for the specific accessor, which might be a user identifying number. Permission: The combination of a subject and an action is a permission. So, for example, being able to download files from a particular folder in a file repository would be a permission. Assignment: In RBAC there is never a direct link between an accessor and permission to perform an action on a subject. Instead, accessors are allocated one or more roles. The linking of an accessor and role is an assignment. Role: A role is the bearer of permissions and is similar to the notion of a group. It is roles that are granted one or more permissions. It is easy to see that we can control what can be done by allocating roles to users, and then checking to see if any of a user's roles has a particular permission. Moreover, we can generalize this beyond users to other types of accessor as the need arises. The model built so far is known in the academic literature as RBAC0. Adding Hierarchy As RBAC can operate at a much more general level than ACL, it will often happen that one role embraces another. Suppose we think of the example of a hospital, the role of consultant might include the role of doctor. Not everyone who has the role of doctor would have the role of consultant. But all consultants are doctors. At present, Aliro implements hierarchy purely for backwards compatibility with the Mambo, and Joomla! schemes, where there is a strict hierarchy of roles for ACL. The ability to extend hierarchy more generally is feasible, given the Aliro implementation, and may be added at some point. The model with the addition of role hierarchies is known as RBAC1. Adding Constraints In general data processing, situations arise where RBAC is expected to implement constraints on the allocation of roles. A typical example would be that the same person is not permitted to have both purchasing and account manager roles. Restrictions of this kind derive from fairly obvious principles to limit scope for fraud. While constraints can be powerful additions to RBAC, they do not often arise in web applications, so Aliro does not presently provide any capability for constraints. The option is not precluded, since constraints are typically grafted on top of an RBAC system that does not have them. Adding constraints to the basic RBAC0 model creates an RBAC2 model, and if both hierarchy and constraints are provided, the model is called RBAC3. Avoiding Unnecessary Restrictions When it comes to design an implementation, it would be a pity to create obstacles that will be troublesome later. To achieve maximum flexibility, few restrictions are placed on the information that is stored by the RBAC system. Subjects and accessors have both types, and identifiers. The types can be strings, and there is no need for the RBAC system to limit what can be used in this respect. A moderate limitation on length is not unduly restrictive. It is up to the wider CMS to decide, for example, what kinds of subjects are needed. Our example for this article is the file repository, and the subjects it needs are known to the designer of the repository. All requests to the RBAC system from the file repository will take account of this knowledge. Identifiers will often be simple numbers, probably derived from an auto-increment primary key in the database. But it would be unduly restrictive to insist that identifiers must be numbers. It may be that control is needed over subjects that cannot be identified by a number. Maybe the subject can only be identified by a non-numeric key such as a URI, or maybe it needs more than one field to pick it out. For these reasons, it is better to implement the RBAC system with the identifiers as strings, possibly with quite generous length constraints. That way, the designers of software that makes use of the RBAC system have the maximum opportunity to construct identifiers that work in a particular context. Any number of schemes can be imagined that will combine multiple fields into a string; after all, the only thing we will do with the identifier in the RBAC system is to test for equality. Provided identifiers are unique, their precise structure does not matter. The only point to watch is making sure that whatever the original identifier may be, it is consistently converted into a string. Actions can be simple strings, since they are merely arbitrary labels. Again, their meaning is important only within the area that is applying RBAC, so the actual RBAC system does not need to impose any restrictions. Length need not be especially large. Roles are similar, although systems sometimes include a table of roles because extra information is held, such as a description of the role. But since this is not really a requirement of RBAC, the system built here will not demand descriptions for roles, and will permit a role to be any arbitrary string. While descriptions can be useful, it is easy to provide them as an optional extra. Avoiding making them a requirement keeps the system as flexible as possible, and makes it much easier to create roles on the fly, something that will often be needed. Some Special Roles Handling access controls can be made easier and more efficient by inventing some roles that have their own special properties. Aliro uses three of these: visitor, registered, and nobody. Everyone who comes to the site is counted as a visitor, and is therefore implicitly given the role visitor. If a right is granted to this role, it is assumed that it is granted to everybody. After all, it is illogical to give a right to a visitor, and deny it to a user who has logged in, since the user could gain the access right just by logging out. For the sake of efficient implementation of the visitor role, two things are done. One is that nothing is stored to associate particular users with the role, since everyone has it automatically. Second, since most sites offer quite a lot of access to visitors prior to login, the visitor role is given access to anything that has not been connected with some more specific role. This means, again, that nothing needs to be stored in relation to the visitor role. Almost as extensive is the role registered, which is automatically applied to anyone who has logged in, but excludes visitors who have not logged in. Again, nothing is stored to associate users with the role, since it applies to anyone who identifies themselves as a registered user. But in this case, rights can be granted to the registered role. Rather like the visitor role, logic dictates that if access is granted to all registered users, any more specific rights are redundant, and can be ignored. Finally, the role of "nobody" is useful because of the principle that where no specific access has been granted, a resource is available to everyone. Where all access is to be blocked, then access can be granted to "nobody" and no user is permitted to be "nobody". In fact, we can now see that no user can be allocated to any of the special roles since they are always linked to them automatically or not at all. Implementation Efficiency Clearly an RBAC system may have to handle a lot of data. More significantly, it may need to deal with a lot of requests in a short time. A page of output will often consist of multiple elements, any or all of which may involve decisions on access. A two pronged approach can be taken to this problem, using two different kinds of cache. Some RBAC data is general in nature, an obvious example being the role hierarchy. This applies equally to everyone, and is a relatively small amount of data. Information of this kind can be cached in the file system so as to be available to every request. Much RBAC information is linked to the particular user. If all such data were to be stored in the standard cache, it is likely that the cache would grow very large, with much of the data irrelevant to any particular request. A better approach is to store RBAC data that is specific to the user as session data. That way, it will be available for every request by the same user, but will not be cluttered up with data for other users. Since Aliro ensures that there is a live session for every user, including visitors who have not yet logged in, and also preserves the session data at login, this is a feasible approach. Where are the Real Difficulties? Maybe you think we already have enough problems to solve without looking for others? The sad fact is that we have not yet even considered the most difficult one! In my experience, the real difficulties arise in trying to design a user interface to deal with actual control requirements. The example used in this article is relatively simple. Controlling what users can do in a file repository extension does not immediately introduce much complexity. But this apparently simple situation is easily made more complex by the kind of requests that are often made for a more advanced repository. In the simple case, all we have to worry about is that we have control over areas of the repository, indicating who can upload, who can download, and who can edit the files. Those are the requirements that are covered by the examples below. Going beyond that, though, consider a situation that is often discussed as a possible requirement. The repository is extended so that some users have their own area, and can do what they like within it. A simple consequence of this is that we need to be able to grant those users the ability to create new folders in the file repository, as well as to upload and edit files in the existing folders. So far so good! But this scenario also introduces the idea that we may want the user who owns an area of the repository to be able to have control over certain areas, which other users may have access to. Now we need the additional ability to control which users have the right to give access to certain parts of the repository. If we want to go even further, we can raise the issue of whether a user in this position would be able to delegate the granting of access in their area to other users, so as to achieve a complete hierarchy of control. Handling the technical requirements here is not too difficult. What is difficult is designing user interfaces to deal with all the possibilities without creating an explosion of complexity. For an individual case it is feasible to find a solution. An attempt to create a general solution would probably result in a problem that would be extremely hard to solve. Summary In this part of the article we had a look at the highly flexible role-based access control system. We established the principles using standard notions of RBAC. We discussed about the specific details, such as the way accessors and subjects are identified are adapted to the particular situation of a CMS framework. In part 2 of the article, we will look at the database implementation and the code for administering RBAC. We will also consider in outline how questions about access can be answered.  
Read more
  • 0
  • 0
  • 2259
article-image-change-control-personal-projects-subversion-style
Packt
21 Oct 2009
5 min read
Save for later

Change Control for Personal Projects - Subversion Style

Packt
21 Oct 2009
5 min read
Who Should Read This Read on if you are new to change control, or believe that change control only applies to software, or that it is only meant for large projects. If you are a software pro working with large software projects, you can still read this if you want a gentle introduction to Subversion or svn as it is called. Introduction We have all heard those trite remarks about change -- “... change is the only constant ...”, or similar ones, especially before an unpleasant corporate announcement. These overused remarks about change are unfortunately true. During the course of a day, we make numerous (hopefully!) interrelated changes, updates, or transformations to our work products to reach specific project goals. Needless to say, these changes need to be tracked along with the rationale behind each if we are to prevent ourselves from repeating mistakes, or simply want to recall why we did what we did one month ago! Note that we are not talking about only code or documents here; your work products could be a portfolios of photographs, animations, or some arbitrary binary format. A change control discipline also gives you additional advantages such as being able to develop simultaneous versions of work products for different purposes or clients, rolling back to a previous arbitrary version, or setting up trial development in a so-called branch to bring it back to the main work stream after due review. You also have a running history of how your work product has evolved over time and features. Fetching from a change managed repository also prevents you from creating those fancifully named multiple copies of a file just to keep track of its versions. To reiterate: we use the words 'work product' and 'development' in the broadest sense and not just as applied to software. You might as well be creating a banner ad for your client as much as a Firefox plugin. In the rest of this article we will see how to build a simple personal change control discipline for your day-to-day work using a version control tool. As you will note, 'control' and 'management' have been used interchangeably, though a little hair splitting will yield rich dividends in terms of how different these terms are. Subversion Subversion is version control system available on the Linux (and similar) platforms. If you are trapped in a proprietary world by choice, circumstance, or compulsion, you should try TortoiseSVN. Here, we confine ourselves to the Linux platform. Subversion works by creating a time line of your work products from their inception (or from the point they are brought under version control) to the present point in time, by capturing snapshots of your work products at discrete points that you decide. Each snapshot is a version. You can traverse this time line and extract specific versions for use. How does subversion do it? It versions entire directories. A new version of your directory will be created even if you change one file in it. Don't worry; this does not lead to an explosion of file size with each version. Explaining some terminology, albeit informally, should make the going easier from here. Subversion stores your project(s) in a repository. For the purpose of this article, our repository will stay on the local machine. A revision is nothing but a particular snapshot of the project directory. A working directory is your sandbox. This is where you check out a particular version of your project directory from the repository, make any modifications to it, and then do a check in back into the repository. Revision numbers are bumped up with each check in. You can revert a configuration item, which is like undoing any changes you made. If all this sounds a little abstruse, don't worry, because we will shortly set up our repository so that you can try things out. A commit is when you...., well commit a change done to a file into the repository. Subversion is mostly bundled with a Linux distribution. Find out if you have yours with a 'man svn' or 'svn -h' or a 'whereis svn' command. Setting up Your Repository You can set up your repository in your home directory if you are working on a shared environment. If you have a machine to yourself, you might want to create an 'svn' account with /sbin/nologin (politely refuses logins) as the shell. Your repository might then be '/home/svn/repos'. Subversion is a command line tool. But the only command you will ever issue for the purpose of this article will be to set up your repository: $ svnadmin create /path/to/your/repository The rest, as they say, is GUI! Let Us Get Visual A GUI for subversion is a great tool for learning and working even if you decide to settle for the command line once you get more proficient. eSvn (http://zoneit.free.fr/esvn/) is a Qt-based graphical front end for Subversion. Follow the instructions with the download to compile and install eSvn. Run esvn and this is how it will look with the File | Options... dialog open. Make sure you enter the correct path to svn if not for the other items.    
Read more
  • 0
  • 0
  • 1793

article-image-extending-project-governance-for-service-oriented-architecture-part1
Packt
21 Oct 2009
12 min read
Save for later

Extending Project Governance for Service Oriented Architecture-part1

Packt
21 Oct 2009
12 min read
As a part of informative conversation, we have Adil — IT Manager for Home Insurance Systems, Elena — Chief Architect, Jennifer — Project Manager for Auto Insurance Systems, Mark — Project Manager for Home Insurance Systems and Service Manager for Customer Information Service, Mike — IT Manager for Insurance Products, Raj — Technical Lead and Member of SOA Center of Excellence, Ramesh — Solution Architect for Annuity Systems, Spencer — Member of Enterprise Architecture Team and finally Alexandra — Spencer's wife as the key characters. Every organization's journey to SOA adoption must begin somewhere. Some organizations may take a very top-down approach based upon direction from the Chief Information Officer (CIO) or other senior IT leader, while other organizations may begin with a grass-roots effort from within the IT organization, often times during a single project. Beginning the SOA Journey Spencer walked in through the main doors of Advasco, a leading financial conglomerate, on Monday morning knowing it was going to be a busy day. He was part of the Enterprise Architecture team at Advasco, and immediately headed for his weekly meeting with his boss, Elena, the Chief Architect. "Come on in, Spencer," she said. "As you know, we've been given a big challenge over the next few months." Late last week, the head of the sales and marketing for the insurance division announced that they needed to improve the way they interacted with their customers. Advasco began as a typical financial services company, but had recently expanded into the insurance area through acquisition. They began by acquiring a company that provided homeowner's policies in several Midwest states. Over the next few years, Advasco had acquired several other regional insurance companies. This resulted in an increase in the number of insurance products that it offered, as well as turning Advasco into a nationwide provider. Unfortunately, Advasco was struggling to increase the number of insurance products per customer. Analysis of the situation had determined that while the sales staff of the original organizations had been combined, each of the different insurance products relied on different applications for customer management. As a result, it was far more difficult for the sales agents to know what insurance products any given customer had. After discussing it with Mike, the IT manager supporting insurance products, IT was given the task of providing the sales agents and marketing staff for the insurance division with a single view of the customer. Elena then said to him, "I had a meeting with Mike to discuss their new initiative to provide a single view of the customer to the sales agents and marketing staff. While he has some great developers in his area, he asked me if Enterprise Architecture could provide some architectural guidance to their effort. Given the excellent integration work you did when Advasco acquired our first company in the insurance area, I think you'd do a great job on this effort." "It certainly sounds like an exciting project," said Spencer, "I'd love to help out. Just last week, I met with my own insurance agent and saw first hand the frustration he had in trying to see the different insurance products that I have for my family." "I'm glad to hear that," said Elena, "I'd like you to meet with Mike today and start coming up with an architecture for the effort. I know you've been reading about SOA. Perhaps this effort can serve as a good pilot for some of the techniques." Spencer agreed. He left Elena's office and went to his desk to set up a meeting with Mike. This was going to be an exciting effort. This initiative was highly visible within the organization, since Advasco's customer approval rating had been taking a beating over the past two years. In addition, Elena knew that Spencer had been researching SOA. In his reading, he felt that SOA had great potential to change the way that Advasco built applications. This effort would provide an opportunity to try out some of the technologies associated with it. Later that afternoon, Spencer met with Mike to go through the existing applications. Mike said, "Unfortunately, the situation is a mess. Right now, the application that handles our auto insurance business is completely independent from the application that handles our home insurance business. The same thing is true for the life insurance business. They each have their own databases, requiring our agents to enter all of the customer information in multiple times. It creates a nightmare for our billing department, especially when trying to compute discounts for multiple policy holders. These applications have all been built using different technologies, including COBOL, VB.NET, and Java." Spencer said, "Well, let's take a managed approach to this effort. Which are the two insurance lines where we most frequently see repeat customers?" Mike replied, "The most common case is for a customer to hold both an auto insurance policy and a homeowner's policy. It's an easy way to get a multiple policy discount." "Well, why don't we start with those two systems and see what we can do. I've been reading about SOA and I think it could provide the right approach for this effort." "I'll trust you on this one Spencer. Elena spoke very highly of you in our meeting last week. As long as you don't think adopting new approaches will impact the timelines, I'm okay with it. The insurance sales and marketing group is under a ton of pressure to get our customer approval rating back up where it should be as quickly as possible." The next day, Spencer met with the managers responsible for the auto insurance systems and the home insurance systems. Spencer kicked off the meeting, "We're here to discuss how we can make things better for our sales staff. Right now, they have to deal with two separate applications. As a result, sometimes they don't know when they're dealing with someone who is already a customer. Other times, we wind up with inconsistent records across the two systems, or have problems keeping records up-to-date when a customer moves." Tim, the manager for the auto insurance systems immediately jumped into the conversation, "If we could get the home insurance system to use our customer database, our problems would go away." Adil, the manager for the home insurance systems, responded to Tim, "We've spent the last 15 years evolving our application and database. It would be much more expensive for us to try to move all our data into your system." Spencer could sense the tension in the room. Both of these managers had invested many years in their systems, and neither one wanted to relinquish any amount of control. "I don't think consolidating the data will work with the timelines we've been given. What I'd like to do is to create a new customer information service that will provide an abstraction layer in front of both of your databases. You'll both need to modify your applications to use the service rather than going directly to the database, but the service will ensure that both systems remain in sync. In addition, you'll have access to additional information about the customers in each other's systems that you can now incorporate into your applications. Then, at a later time, we can pursue consolidating the databases into a single one. With the service in place, you won't need to make any changes to the front end of your applications when that occurs." Adil said, "How are you going to make this work? My system leverages a Java front-end talking to our mainframe, while Tim's system is based completely on Microsoft technologies?" Spencer responded, "I think this a great opportunity to leverage web services technology. It claims to provide interoperability across these platforms, let's give it a try." Tim said, "Who's going to write this service?" Spencer suggested, "Since we need to incorporate information from both of your systems, I suggest that we form a team with a developer from each of your groups to design and build the new service." Adil and Tim agreed, and told Spencer that they would let him know what developers they would contribute to the effort. Spencer went back to his desk and knew that he had a real challenge on his hands. While the managers involved had committed developers to the effort, he also sensed that there was some hesitancy about the effort. They knew that changes were needed, but it was clear that neither one wanted to give up the control they currently had over their systems. He was hoping that the right developers would get assigned. He knew that many of them had complained about the redundancy that existed across the various applications, but the scope and timeline of their projects prevented them from doing anything about it. This effort was beginning with the right scope, so as long they met timelines, there was a good chance to make it happen. Over the next few weeks, Spencer's team, including the developers from Adil and Tim's organizations, worked hard to define the new Customer service that both applications would use. The developers were very familiar with the current data models used by each application, and worked together to define the data models and schemas for the new service. While these developers had some knowledge of how the existing applications manipulated the data, they worked solely with each other in defining the functional interface of the service. In the end, the service interface contained some elements of Customer data that was specific to one of the two applications, but they felt that information could be safely ignored by the other application. The First Milestone Soon afterwards, Spencer met with Jennifer, the project manager for the auto insurance application, to discuss their schedule. Spencer said, "Hi Jennifer. I wanted to discuss our delivery schedule with you so we can ensure that you can integrate the new Customer service as part of your effort. I know you're making some additional changes to the application besides the migration to the service." Jennifer took a glance at her project plan and told Spencer, "We're currently planning on going live on October 6th. Our performance tests are planned for September 2nd, and user testing will begin on July 28th." Spencer said, "Okay, we'll plan on targeting those same dates for our service. Don't hesitate to contact me if you need anything else." Jennifer didn't. Just two weeks later she sent him an email that said, "Spencer, my developers want to know when they'll have a service they can test against. They've told me that they can't do anymore work until it's available." Spencer replied, "I'll have one of my developers provide you the URL for our development service right away." He had his team provide it, and didn't hear anything back from Jennifer's team, so he assumed everything was working well. That lasted for about one week when Jennifer came storming into his cubicle. "What did you do to the service? We were going to demonstrate where we were to one of our users today, and the application crashed when we tried retrieving data," she said. It was clear that it had not been a good morning for her. "We've been testing the integration with the home insurance data system, and have run into some issues, so our development environment has been up and down all day long as we try to determine what the problem is," he replied. "Well, you'd better get it fixed soon. I now have a key user who's very nervous about the stability of this new service-based approach, and my developers are simply telling me that they can't do anything about it. I'm going to report this as a serious issue in our Project Management Office (PMO) update on Thursday." "I'll get right on it, Jennifer. I apologize for this and we'll get it fixed as quickly as we can." Spencer immediately realized where his mistake was. By giving Jennifer's team the URL for the service in his development environment, he was exposing her application to all of the instability that is normally associated with any development environment. From her perspective, however, she didn't care about his development environment; she needed something that was stable so she could execute her tests and provide demonstrations. He gathered his developers and told them that they needed to create a stable version of the service that would be separate from their own development efforts that the auto insurance application could use. He suggested that they determine which of their iterations represented a key milestone from the perspective of the auto insurance application. When those iterations were successfully completed, it would be promoted to the stable environment in use by the auto insurance application. They implemented this plan and things got better, at least from Jennifer's perspective. Unfortunately, Jennifer wasn't the only project manager whose effort was dependent on Spencer's team. Mark was the project manager for the home insurance application, the other consumer of this new service. Like his initial meeting with Jennifer, Spencer met with Mark to find out what his plans were for the home insurance application. Like Jennifer, there were additional changes that Mark was putting into
Read more
  • 0
  • 0
  • 2312

article-image-selinux-highly-secured-web-hosting-python-based-web-applications
Packt
21 Oct 2009
10 min read
Save for later

SELinux - Highly Secured Web Hosting for Python-based Web Applications

Packt
21 Oct 2009
10 min read
When contemplating the security of a web application, there are several attack vectors that you must consider. An outsider may attack the operating system by planting a remote exploit, exercising insecure operating system settings, or brandishing some other method of privilege escalation. Or, the outsider may attack other sites contained in the same server without escalating privileges. (Note that this particular discussion does not touch upon the conditions under which an attack steals data from a single site. Instead, I'm focusing on the ability to attack different applications on the same server.) With hosts providing space for large numbers of PHP-based sites, security can be difficult as the httpd daemon traditionally runs under the same Unix user for all sites. In order to prevent these kinds of attacks from occurring, you need to concentrate on two areas: Preventing the site from reading or modifying the data of another site, and Preventing the site from escalating privileges to tamper with the operating system and bypass user-based restrictions. There are two toolboxes you use to accomplish this. In the first case, you need to find a way to run all of your sites under different Linux users. This allows the traditional Linux filesystem security model to provide protection against a hacked site attacking other sites on the same server. In the second case, you need to find a way to prevent a privilege escalation to begin with and barring that, prevent damage to the operating system should an escalation occur. Let's first take a look at a method to run different sites under different users. The Python web framework provides several versatile methods by which applications can run. There are three common methods: first, using Python's built-in http server; second, running the script as a CGI application; and third, using mod_python under Apache (similar to what mod_perl and mod_php do). These methods have various disadvantages: respectively, a lack of scalability, performance issues due to CGI application loading, and the aforementioned “all sites under one user” problem. To provide a scalable, secure, high-performance framework, you can turn to a relatively new delivery method: mod_wsgi. This Apache module, created by Graham Dumpleton, provides several methods by which you can run Python applications. In this case, we'll be focusing on the “daemon” mode of mod_wsgi. Much like mod_python, the daemon mode of mod_wsgi embeds a Python interpreter (and the requisite script) into a httpd instance. Much like with mod_python, you can configure sites based on mod_wsgi to appear at various locations in the virtual directory tree and under different virtual servers. You can also configure the number and behavior of child daemons on a per-site basis. However, there is one important difference: with mod_wsgi, you can configure each httpd instance to run as a different Linux user. During operation, the main httpd instance dispatches requests to the already-running mod_wsgi children, producing performance results that rival mod_python. But most importantly, since each httpd instance is running under a different Linux user, you can apply Linux security mechanisms to different sites running on one server. Once you have your sites running on a per-user basis, you should next turn your attention to preventing privilege escalation and protecting the operating system. By default, the Targeted mode of SELinux provided by RedHat Enterprise Linux 5 (and its free cousins such as CentOS) provides strong protection against intrusions from httpd-based applications. Because of this, you will need to configure SELinux to allow access to resources such as databases and files that reside outside of the normal httpd directories. To illustrate these concepts, I'll guide you as you install a Trac instance under mod_wsgi. The platform is CentOS 5. As a side note, it's highly recommended that you perform the installation and SELinux debugging in a XEN instance so that your environment only contains the software that is needed. The sidebar explains how to easily install the environment that was originally used to perform this exercise, and I will assume that is your primary environment. There are a few steps that require the use of a C compiler – namely, the installation of Trac – and I'll guide you through migrating these packages to your XEN-based test environment. Installing Trac In this example, you'll use a standard installation of Trac. Following the instructions provided in the URL in the Resource section, begin by installing Trac 0.10.4 with ClearSilver 0.10.5 and SilverCity 0.9.7. (Note that with many Python web applications such as Trac and Django, “installing” the application means that you're actually installing the libraries necessary for Python to run the application. You'll need to run a script to create the actual site.) Next, create a PostgreSQL user and database on a different machine. If you are using XEN for your development machine, you can use a PostgreSQL database running in your main DOM0 instance; all we are concerned with is that the PostgreSQL instance is accessed on a different machine over the network. (Note that MySQL will also work in this example, but SQLite will not. In this case, we need a database engine that is accessed over the network, not as a disk file.) After that's done, you'll need to create an actual Trac site. Create a directory under /opt, such as /opt/trac. Next, run the trac_admin command and enter the information prompted. trac-admin /opt/trac initenv Installing mod_wsgi You can find mod_wsgi at the source listed in the Resources. After you make sure the httpd_devel package is installed, installing mod_wsgi is as simple as extracting the tarball and issuing the normal ./configure and 'make install' commands. Running Trac under mod_wsgi If you look under /opt/trac, you'll notice two directories: one labeled apache, and one with the label of the project that you assigned when you installed this instance of Trac. You'll start by creating an application script in the apache directory. The application script is listed in Listing 1. Listing 1: /opt/trac/apache/trac.wsgi #!/usr/bin/python import sys sys.stdout = sys.stderr import os os.environ['TRAC_ENV'] = '/opt/trac/test_proj' import trac.web.main application = trac.web.main.dispatch_request (Note the 'sys.stdout = sys.stderr' line. This is necessary due to the way WSGI handles communications between the Python script and the httpd instance. If there is any code in the script that prints to STDOUT (such as debug messages), then the httpd instance can crash.) After creating the application script, you'll modify httpd.conf to load the wsgi module and set up the Trac application. After the LoadModule lines, insert a line for mod_wsgi: LoadModule wsgi_module modules/mod_wsgi.so Next, go to the bottom of httpd.conf and insert the text in Listing 2. This text configures the wsgi module for one particular site; it can be used under the default httpd configuration as well as under VirtualHost directives. Listing 2: Excerpt from httpd.conf: WSGIDaemonProcess trac user=trac_user group=trac_user threads=25 WSGIScriptAlias /trac /opt/trac/apache/trac.wsgi WSGIProcessGroup trac WSGISocketPrefix run/wsgi <Directory /opt/trac/apache> WSGIApplicationGroup %{GLOBAL} Order deny,allow Allow from all </Directory> Note the WSGIScriptAlias identifier. The /trac keyword (first parameter) specifies where in the directory tree the application will exist. With this configuration, If you go to your server's root address, you'll see the default CenOS splash page. If you add /trac after the address, you'll hit your Trac instance. Save the httpd.conf file. Finally, add a Linux user called trac_user. It is important that this user should not have login privileges. When the root httpd instance runs and encounters the WSGIDaemonProcess directive noted above, it will fork itself as the user specified in the directive; the fork will then load Python and the indicated script.     Securing Your Site In this section, I'll focus on the two areas noted in the introduction: User based security and SELinux. I will touch briefly on the theory of SELinux and explain the nuts and bolts of this particular implementation in more depth. I highly recommend that you read the RedHat Enterprise Linux Deployment Guide for the particulars about how RedHat implements SELinux. As with all activities involving some risk, if you plan to implement these methods, you should retain the services of a qualified security consultant to advise you about your particular situation. Setting up the user-based security is not difficult. Because the HTTPD instance containing Python and the Trac instance will run under the Trac user, you can safely set everything under /opt/trac/test_project for read and execute (for directories) for user and none for group/all. By doing this, you will isolate this site from other sites and users on the system. Now, let's configure SELinux. First, you should verify that your system is running the proper Policy and Mode. On your development system, you'll be using the Targeted policy in its Permissive mode. If you choose to move your Python applications to a production machine, you would run under the Targeted policy, in the Enforcing mode. The Targeted policy is limited to protecting the most popular network services without making the system so complex as to prevent user-level work from being done. It is the only mode that ships with RedHat 5, and by extension, CentOS 5. In Permissive mode, SELinux policy violations are trapped and sent to the audit log, but the behavior is allowed. In enforcing mode, the violation is trapped and the behavior is not allowed. To verify the Mode, run the Security Level Configuration tool from the Administration menu. The SELinux tab, shown in Figure 1, allows you to adjust the Mode. After you have verified that SELinux is running in Permissive mode, you need to do two things. First, you need to change the Type of the files under /opt/trac. Second, you need to allow Trac to connect to the Postgres database that you configured when you installed Trac. First, you need to tweak the SELinux file types attached to the files in your Trac instance. These file types dictate what processes are allowed to access them. For example, /etc/shadow has a very restrictive 'shadow' type that only allows a few applications to read and write it. By default, SELinux expects web-based applications – indeed, anything using Apache – to reside under /var/www. Files created under this directory have the SELinux Type httpd_sys_content_t. When you created the Trac instance under /opt/trac, the files were created as type usr_t. Figure 2 shows the difference between these labels To properly label the files under /opt, issue the following commands as root: cd /optchcon -R -t httpd_user_content_t trac/ After the file types are configured, there is one final step to do: allow Trac to connect to PostgreSQL. In its default state, SELinux disallows outbound network connections for the httpd type. To allow database connections, issue the following command: setsebool -P httpd_can_network_connect_db=1 In this case, we are using the -P option to make this setting persistent. If you omit this option, then the setting will be reset to its default state upon the next reboot. After the setsebool command has been run, start HTTPD by issuing the following command: /sbin/service httpd start If you visit the url http://127.0.0.1/trac, you should see the Trac screen such as that in Figure 3.    
Read more
  • 0
  • 0
  • 8965
article-image-date-and-calendar-module-drupal-5-part-2
Packt
21 Oct 2009
6 min read
Save for later

Date and Calendar Module in Drupal 5: Part 2

Packt
21 Oct 2009
6 min read
Recipe 40: Timeline Ingredients Timeline module: http://www.drupal.org/project/timeline Timeline widget:http://www.miccolis.net/random/timeline-1-2.tar.gz The Timeline module implements a nice interactive script developed originally by the SIMILE project at MIT. The project "graduated" in 2008, to become its own stand-alone open source project, hosted at Google Code. Log on to the host and enter the following commands. This is almost a garden-variety module installation, however, we also need to download all of the SIMILE timeline code and place it in an api subdirectory. The Timeline widget tarball expands to the timeline-1-2 directory, so in the last step we use the mv command to rename it to api. cd home/DRUPALACCOUNT/public_html/sites/all/moduleswget http://ftp.drupal.org/files/projects/timeline-5.x-1.0.tar.gztar xvf timeline-5.x-1.0.tar.gzcd timeline/wget http://www.miccolis.net/random/timeline-1-2.tar.gz tar xvf timeline-1-2.tar.gz mv timeline-1-2 api Enable the Timeline module. Explore the configuration settings at admin/settings/timeline. Here you may set the width, height, and initial date focus. Also note the Advanced settings for the path to the Timeline widget JavaScript. If, for some reason, you are unsuccessful making the widget available, you may temporarily try pointing to: http://simile.mit.edu/timeline/api/timeline-api.js. (This will work for as long as MIT continues to host this.) Read the README.txt file, and INSTALL.txt file (this is always a good practice when installing new modules). This is a summary of the Views field requirements for setting up a timeline in Drupal. If present If not present First field Date or Event determines location on the timeline Defaults to Node Created Time Second Field Title, with clickable link Node's default title is used Third Field Description Teaser, if available. (CCK Date fields do not have timeline) Additional Fields Additional fields are not used by Timeline. Edit the timeline view created in Recipe 34. In the Page fieldset, change the View Type to Timeline: Horizontal. Scroll down to the Fields fieldset. Note that in our original view, the Title is the first field followed by Date as the second field. We will reverse this. Click on the up arrow in the Date row to Move this item to the top. Add the Text: Description (field_workshop_description) as the third field. Save the view and browse to timeline. Move the cursor around the timeline. Click on the events to see the associated pop-up box. Click and drag to the left to go forward in time. Click and drag works in both the upper and lower timeline bands. Configuration settings for individual timelines are available at admin/build/timeline (these settings will override default settings at admin/settings/timeline). A particularly interesting setting is the one to enable controls. With controls enabled, the user will have the opportunity to filter, or highlight the timeline based on text either in the title or the description. Regular expressions will also work when filtering or highlighting timeline items. Cooking|Recipes Find items that contain either Cooking or Recipes in the title or description ^L Find titles that start with L asagna Find Lasagna-partial words work fine. hea[rl]t Find Health or Heart The searches are case-insensitive. Recipe notes For examples of basic and sophisticated SIMILE Timelines see http://simile.mit.edu/timeline/examples/. More information about Timeline is available at http://code.google.com/p/simile-widgets/ including a mailing list, a wiki, and an independent issue queue for various SIMILE web widgets. There is also an archived listerv available at http://www.nabble.com/SIMILE---General-f27660.html. The listserv remains active for other SIMILE projects but does not accept content regarding "graduated" projects such as Timeline. However, you may find older posts helpful. If you like Timeline, try some of the other SIMILE projects as well, at http://simile.mit.edu/. (Perhaps you can write the next module to make them available in Drupal.) Exposed Filters are incompatible with the Timeline module. Arguments will work. For instance, if you add a Taxonomy item argument the URL: http://YOURSITE.com/timeline/Cooking would show only the workshops in the Cooking category. To incorporate color coding by taxonomy, consider installing the patch at http://drupal.org/node/121298. There is also a nice patch to include icons by taxonomy term at http://drupal.org/node/104890. The Timeline module integrates with the Events module. If no fields are included in the timeline, the timeline displays the date the content was posted. Recipe 41: Views Popup Ingredients Completed Recipe 34, views_popup view Views Popup module: http://drupal.org/project/views_popup The Views Popup module displays a list of up to three fields and then, upon mouseover, displays additional fields in a pop-up box. This is not a date-specific module, but we'll use it to display a workshop description when you move the mouse over the date. We'll also take a look at the views_style_plugins hook, which in this article enabled the Date Browser, Timeline, Calendar, and now List View as Popup View Types. Install and enable the Views Popup module. Open the views_popup view at views_popup/edit. In the Page fieldset, change the View Type to List View as Popup, Show 2 Fields In the Fields fieldset, change the order of the Datestamp and Title fields so that the datestamp is first. Add the Text: Description (field_workshop_description) field. The first two of these fields will display. The third will be hidden by default. Save and view the views_popup view. Note than when you mouse over the date, the description appears Take a look at hook_views_style_plugins in the views_popup.module file: function views_popup_views_style_plugins() { return array( 'list_hint' => array( 'name' => t('List View as Popup, Show 1 field'), 'theme' => 'views_view_list_hint_popup1', 'validate' => 'views_ui_plugin_validate_list', 'needs_fields' => true, 'weight' => -10, ), 'list_hint2' => array( 'name' => t('List View as Popup, Show 2 fields'), 'theme' => 'views_view_list_hint_popup2', 'validate' => 'views_ui_plugin_validate_list', 'needs_fields' => true, 'weight' => -10, ), 'list_hint3' => array( 'name' => t('List View as Popup, Show 3 fields'), 'theme' => 'views_view_list_hint_popup3', 'validate' => 'views_ui_plugin_validate_list', 'needs_fields' => true, 'weight' => -10, ) ); The critical elements in this array are the name and the specified theme callback function. The function appears below in the same file and does the actual work of producing the output, in this case, creating a pop-up. Recipe notes Documentation on hook_views_style_plugins is available in the Drupal handbook at http://drupal.org/node/193448. Think of the style plugin as a way to modify the output of a whole node, while the field formatters apply to a single field.
Read more
  • 0
  • 0
  • 2321

article-image-installing-and-using-openfire
Packt
21 Oct 2009
6 min read
Save for later

Installing and Using Openfire

Packt
21 Oct 2009
6 min read
The Openfire instant messaging server is very easy to install. In fact, it's totally newbie-proof. So much so, that unlike other complex server software, even if you've never setup up Openfire before, you'll be able to get it up and running on your first try. If you're sceptical, by the time we are done with this short article, we'll have ourselves a fully-functional Openfire server that will register users and connect with clients. Preparing Your System Openfire is a cross-platform server and can be installed under Linux, Solaris, Mac, or Windows operating system environments. Openfire reserves its enormity for its users. When it comes to system requirements, Openfire is very suave and a perfect gentleman who has very moderate demands. You don't need to spend much time preparing your system for installing Openfire. Just pick out the environment you're comfortable with—Windows or one of the popular Linux distributions such as Fedora, Debian, or Ubuntu, and you're good to go. You don't have to run around getting obscure libraries or worry about mismatched versions. But like any hard-working gentleman, Openfire has a thing for caffeine, so make sure you have Java on your system. No need to run to the kitchen—this isn't the Java in the cupboard. Openfire is written in the Java programming language, so it'll need a Java Runtime Environment (JRE) installed on your system. A JRE creates a simple (breathable, so to say) environment for Java applications to live and function in. It's available as a free download and is very easy to install. If you're installing under Windows, just skip to the "Installing Under Windows" section later in the article. Linux Users Get Your Cuppa! Sun's Java Runtime Environment is available as a free download from Sun's website (http://www.java.com/en/download/linux_manual.jsp) or it can also be installed from your distribution's software management repositories. Users of RPM-based systems can safely skip this section because the Openfire installer for their distribution already includes a JRE. On the other hand, users of Debian-based systems such as Ubuntu will have to install the JRE before installing Openfire. Thanks to the popular apt-get package management system, there isn't much to installing the JRE. Because Sun's JRE isn't free and is also not an open source software, most Linux distributions make the JRE package available in their non-free tree. If the following command doesn't work, check out the detailed installation instructions for your specific distribution, at  https://jdk-distros.dev.java.net. Open a console and issue the following command: $ sudo apt-get install sun-java6-jre Now the apt-get system will automatically fetch, install, and activate the JRE for you! Meet The Protagonists This article is about making sure that you have no trouble installing one file. This one file is the Openfire installer and it is available in multiple flavors. The four flavors we're concerned with aren't as exotic as Baskin Robbins' 31 flavors but that doesn't make the decision any easier. The Openfire project releases several installers. The four flavors we're concerned with are: Openfire-3.5.2-1.i386.rpm: RPM package for Fedora Linux and other RPM-based variants Openfire_3.5.2_all.deb: DEB package for Debian, Ubuntu Linux and their derivates Openfire_3_5_2.tar.gz: Compressed "tarball" archive that'll work on any Linux distribution Openfire_3_5_2.exe: Openfire installer for Windows We'll cover installing Openfire from all of these files, so that you may use Openfire from your favorite Linux distribution or from within Windows. Just to reiterate here, the Windows installer and the RPM Linux installer both bundle the JRE, while the other other versions do not. The Actual Install-Bit Alright, so you have the Java JRE setup and you've downloaded the Openfire installer. In this section, we'll install Openfire server from the various versions we discussed in the last section. Let's first install from the source tarball. The first step when dealing with .tar.gz source archive is to extract the files. Let's extract ours under /tmp and then move the extracted directory under /opt. # tar zxvf openfire_3_5_2.tar.gz# mv openfire /opt Now we'll create a non-priviledged user and group for running Openfire. # groupadd openfire# useradd -d /opt/openfire -g openfire openfire Next, we'll change ownership of the openfire/directory to the newly-created user and group. # chown -R openfire:openfire /opt/openfire Believe it or not, that's it! You've just installed Openfire server. Surprised? Get ready for more. It gets even simpler if you install using the precompiled RPM or DEB binaries. In the case of RPM, Openfire is installed under /opt/openfire and in case of the DEB file, Openfire resides under /etc/openfire. On RPM-based systems such as Fedora and its derivates (as root), use: # rpm -ivh openfire-3.5.2-1.i386.rpm On DEB-based systems such as Debian, Ubuntu, and so on, use: $ sudo dpkg -i openfire_3.5.2_all.deb Voila! You're done. Now, who thought my "installing Openfire is totally newbie-proof" comment was an exaggeration? Running Openfire on Linux/Unix So, we now have Openfire on our favourite Linux distribution, whichever distribution this may be. Now it's time to fire it up and get going. Depending on how you installed Openfire, the procedure to start it varies a little. If you've installed Openfire from the RPM or DEB, you'll be pleased to know that the Openfire developers have already done most of the hard work for you. These binaries contain some custom handling for the RedHat/Debian-like environments. You can start and stop Openfire just like any other service on your system: # /etc/init.d/openfire startStarting Openfire: You can also view the other options available: # /etc/init.d/openfireUsage /etc/init.d/Openfire {start|stop|restart|status|condrestart|reload} On the other hand, if you've installed Openfire using the .tar.gz archive, you can start and stop Openfire using the bin/openfire script in your Openfire installation directory. First, change to the user that owns the /opt/openfire directory: # su - openfire# cd /opt/openfire/bin/# ./openfire startStarting Openfire And now you have Openfire up and running! If you are using a firewall, which you most probably are, make sure to forward traffic on ports 5222 and 5223 (for SSL) which clients use for connecting with the Openfire server. Also forward traffic on port 7777 for file transfer. Linux users can skip the next section on installing Openfire under Windows and move directly to the section that discusses the preliminary Openfire setup.
Read more
  • 0
  • 0
  • 5933
Modal Close icon
Modal Close icon