Active4D v5 Reference
Active4D v5 Reference
Product and documentation by Aparajita Fishman Copyright 2001-2010 All rights reserved
Active4D v5
Acknowledgements
First of all, thanks to the makers of PHP for giving me the vision of a better way. Thanks to the client who asked me to generate every single character of HTML in 4D code, which inspired me to come up with a better way. Thanks to Mike Erickson for his convincing me that Active4D was worth doing. He was right. Thanks to all of the users for their feedback and encouragement. And thank you to David Adams for so kindly including a chapter about Active4D in The 4D Web Companion and for allowing me to include his HTTP chapter with these docs.
Active4D v5
Table of Contents
Table of Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23
What is Active4D? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23 HTTP Web Server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23 Server-Side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24 HTML-Embedded . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24 Scripting Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24 Development Environment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24 An Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25 What Can Active4D Do? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25 Database and Protocol Support. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26 A Brief History of Active4D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27
Plugin Archive Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27 Resource Files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27 Shell Archive Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28 Active4D Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28 Web Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29 Demo Archive Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29 Key Files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29 Key File Installation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29 Key File Info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .30 Version Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .30 License Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31 Timeouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31 Trial License. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31 Deployment License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31 OEM License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32 Installation Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32 Starting a Database from Scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32 Installing into a Non-Active4D Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32 Updating an Existing Active4D 4.x Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33 Post-Installation Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33 Configuring for 4Ds Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34 Configuring for NTK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .35 Configuring 4D Client as a Web Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36 Using the Pre- and Post-Execute Hooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36 Pre-Execute Hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36 Post-Execute Hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .37
Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .39
Config File Search Path. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .39 Configuration Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40 The Default Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40
Table of Contents
Active4D v5
Path Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40 The Standard Search Path and Path Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .42 Active4D.ini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .42 ExtensionMap.ini. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44 Realms.ini. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44 VirtualHosts.ini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44
Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .45
Source Code Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .45 Web Server Security = Source Code Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .45 Circumventing Active4D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .45 Potential Attacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .46 Executing/Accessing Non-Web Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .46 The safe script dirs Config Option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .46 Misusing Document Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47 The safe doc dirs Config Option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47 Spoofing Form Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47 The auto create vars Config Option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48 Uploading Huge Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48
Table of Contents
Active4D v5
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Direct Execution68 Uses for Direct Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .68 A4D Execute file. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .68 A4D Execute text. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69 A4D Execute BLOB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69
Interpreter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71
Flow of Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 Embedding Source Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 Input Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 Language Syntax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .73 English Only . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .73 Source Code Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .73 Case Sensitivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .74 Expression-based . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .74 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .75 Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .76 Custom Named Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77 Compiler Declarations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77 Process/Interprocess Variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .78 Array Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .78 Pointer Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79 Extended Boolean Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79 Literals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79 String Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .80 String Interpolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .80 Heredoc Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .83 Date Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .83 Time Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 User-defined Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 Typing of Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 Unary/Assignment Operators. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 In and Not In Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .85 Regular Expression Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .86 String Format Operators. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .86 Picture Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .87 Pointer Dereference Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .87 + Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .87 Character Reference Operator [[]] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .88 Indexing Operator {}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .88 Boolean Operator | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .89 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Control Structures89 for each/end for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .90 break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .90 return. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .90 continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .90 exit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .90 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .91 Working with Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .92 URL-Style (Posix) Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .92
Table of Contents
Active4D v5
Absolute vs. Relative Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .92 Path Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .92 Path Limits. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .93 Including Other Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .93 Uses of Included Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .93 Including Only Once . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .94 Calling 4D Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .94 Parameter Passing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .94 Indirect Method Calls (aka Poor Man's method pointers). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .95 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .95 Collection Handles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .95 Local vs. Global Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .96 Using Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .96 Referencing Collection Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .96 Embedded Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .97 Element Referencing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .97 Iterating Over a Collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .98 HTTP Data Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .98 Request Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .98 _query and _form Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .99 Testing Form Buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .99 Response Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Working with Character Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Platform Character Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Output Character Set. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Output Encoding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 HTTP Request Decoding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Informing the Browser of Your Output Character Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Working with Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Script Timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Defining Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Parameter Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameter Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Scope. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Referencing Global Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pass by Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default Parameters. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Returning Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 105 105 106 106 106 107 108 108 109 110
Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Library Search Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Library Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Importing Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Import Configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Import Errors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 114 114 115 115
Table of Contents
Active4D v5
Automatic Re-Import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Library Namespace. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name Resolution. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Library scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The global library. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Private methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Library-private collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Library Initialization/Deinitialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Storing collections in library-private data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a Poor Mans Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Limitations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
116 116 116 117 117 118 118 119 120 120 122
Table of Contents
Active4D v5
BLOBS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . new collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . new local collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . new global collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collection to blob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blob to collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . save collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . load collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . copy collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deep copy collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . merge collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deep clear collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection array. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection array size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection item count . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set collection array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . is a collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collection has . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count collection items. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete collection item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cryptography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . base64 decode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . base64 encode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blowfish decrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blowfish encrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . md5 sum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Trigger Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Field name. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get field numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get field pointer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QUERY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QUERY BY FORMULA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QUERY SELECTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QUERY SELECTION BY FORMULA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SET QUERY DESTINATION. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Date and Time. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . UTC Commands. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . day of year . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get utc delta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . local datetime to utc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 150 150 151 151 152 152 153 153 154 154 155 156 156 157 157 158 158 159 159 160 161 161 162 163 163 164 165 166 167 168 170 171 171 172 172 173 173 174 174 175 175 175 177 177 178 178 179 179
Table of Contents
Active4D v5
local time to utc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . utc to local datetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . utc to local time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . week of year . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current library name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current line number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current method name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get call chain. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . library list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write to console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get error page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get log level. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . in error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . log message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set error page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set log level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . File Uploads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How File Upload Works. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Referencing File Uploads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Importance of Filename Extensions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Upload Auto-Deletion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . copy upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count uploads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload content type. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload extension. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload remote filename . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload size. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . save upload to field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . When Form Variables Are Query Params (and vice versa) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Posting Raw Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiple-choice Form Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . form variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . form variables has. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variable. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variable choices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variable count . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Locking and Unlocking the Globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . globals has. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
180 180 180 181 182 183 183 183 184 184 185 186 187 187 187 188 188 189 190 190 190 191 191 191 192 192 192 193 193 194 194 195 195 195 195 196 196 196 197 197 198 199 199 200 200 202 202 202 203
Table of Contents
Active4D v5
get global array size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global item. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global keys. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set global array. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete global. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lock globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . unlock globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Iterator Validity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . for each/end for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . more items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . next item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . is an iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . call 4d method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . call method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . choose. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . define . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EXECUTE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . execute in 4d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . for each/end for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Get pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . include into . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . longint to time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . method exists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . nil pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . redirect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . require. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RESOLVE POINTER. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . time to longint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . max of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . min of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . random between . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
204 204 205 205 206 206 207 207 207 208 208 208 209 210 210 210 211 211 211 212 212 213 214 214 215 217 219 219 220 222 223 224 224 225 225 226 227 227 228 228 229 229 229 231 232 232 232
Pictures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Using the image.a4d Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 image.a4d (script file) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
10
Table of Contents
Active4D v5
Loading from the 4D picture library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading from the database via query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading from the database via record number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading from a file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading from an Active4D method call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading from a 4D method call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write gif. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write jpeg. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write jpg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write png . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
234 235 235 235 235 236 236 237 238 239 239
Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 QUERY/QUERY SELECTION. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 ORDER BY. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Query Params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Query Params Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Duplicate Query Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . query params has . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query param . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query param choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query param count . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . build query string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Regular Expressions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pattern Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex callback replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex find all in array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex find in array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex match . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex match all . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex quote pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Request Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . request cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count request cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Request Info. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request infos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count request infos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 242 242 243 243 243 244 244 245 246 247 247 249 249 249 250 251 252 253 254 255 256 259 261 262 262 263 263 264 265 265 265 266
Table of Contents
11
Active4D v5
Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Get indexed string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 STRING LIST TO ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Response Buffer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buffer size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . response buffer size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear response buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response buffer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . save output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . end save output. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set output charset. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get output charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set output encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get output encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write blob. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . writebr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . writeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . writep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write raw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = ................................................................................................. Response Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cookie Fields. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . response cookies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie expires. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie domain. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie path. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count response cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . abandon response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Response Headers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . response headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response header. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count response headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete response header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Response Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get cache control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set cache control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 273 273 273 273 274 274 275 276 276 277 277 278 279 279 281 281 282 282 283 284 284 284 285 285 286 286 287 287 287 288 288 288 289 289 290 291 291 291 292 292 293 294 295 295 295 296
12
Table of Contents
Active4D v5
get expires date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set expires date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get content type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set content type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get content charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set content charset. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Script Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . full requested url . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get license info. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get time remaining. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get version. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . parameter mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . request query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set platform charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get platform charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set script timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get script timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set current script timeout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get current script timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selecting Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading Related Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring Related Record Auto-loading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compatibility with Active4D 2.0.x. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auto relate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ALL RECORDS, FIRST/LAST/NEXT/PREVIOUS RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get auto relations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GOTO RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GOTO SELECTED RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Active4D Session Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Session ID. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Session Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . When Active4D Sends Session Cookies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Session Lifetime. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cookieless Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Memory Caching of Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Session Timeout and Memory Usage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Monitoring Memory Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Session Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session to blob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blob to session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session array size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session item. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
296 296 297 297 297 298 298 299 300 300 300 301 302 302 303 303 303 304 305 305 305 306 307 307 307 308 308 310 310 311 311 312 313 313 313 314 314 315 315 315 316 316 316 318 318 319 319 320 320 321
Table of Contents
13
Active4D v5
get session keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set session array. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session has. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count session items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete session item. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . abandon session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session internal id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . hide session field. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set session timeout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session stats. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . URL Encoding/Decoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String Commands and Unicode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % (formatting operator) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . %% (formatting operator) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . capitalize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . compare strings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . concat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Delete string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . enclose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first not of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . format string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . identical strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Insert string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . interpolate string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last not of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . left trim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . html encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mac to html. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mac to utf8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . param text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Position. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . right trim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . slice string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . split string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Substring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . trim. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url decode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url decode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url decode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url encode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
321 322 323 323 324 324 325 325 325 326 326 327 327 328 328 329 329 329 331 332 333 333 334 335 335 336 337 338 338 339 339 340 340 341 341 342 342 343 343 345 346 347 348 349 350 350 351 351 351 352 352
14
Table of Contents
Active4D v5
url encode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 utf8 to mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 System Documents. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Document Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Document Command Enhancements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Affected Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Error Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Working With Large Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Append document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Create document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . default directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DELETE FOLDER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . directory exists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . directory of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . directory separator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . extension of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . file exists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . filename of. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get root. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . join paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MOVE DOCUMENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . native to url path. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Open document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RECEIVE PACKET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . requested url . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . resolve path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SEND PACKET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SET DOCUMENT POSITION. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . split path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url to native path. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Timestamps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Timestamp Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Timestamp Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Timestamp Normalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Timestamps with Optimistic Locking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . add to timestamp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp difference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp string. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get timestamp datetime. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp year . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp month. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp day . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp hour. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp minute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp second . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp millisecond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 354 354 354 355 355 356 356 356 357 358 358 359 359 359 360 360 360 361 361 362 362 363 363 364 364 365 365 365 366 367 367 367 367 368 370 371 371 372 372 373 373 374 374 374 375 375 376 376
Table of Contents
15
Active4D v5
User Authentication. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auth password . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auth type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auth user . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . authenticate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current realm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . defined . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . local variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set local. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . type descriptor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . undefined . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . variable name. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Plugin Commands. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Base64 decode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Base64 encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Blowfish decrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Blowfish encrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D FLUSH LIBRARY. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Get IP address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Get MAC address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Get root. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D GET SESSION DATA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D GET SESSION STATS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D GET LICENSE INFO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Get MAC address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Get time remaining. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Get version. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Import library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D MD5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Native to URL path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D RESTART SERVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D Set HTTP body callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D SET ROOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D STRIP 4D TAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D URL decode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D URL decode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D URL encode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D URL encode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D URL to native path. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
377 378 378 378 379 379 380 381 381 382 382 383 383 384 385 386 386 386 387 387 388 388 389 389 390 390 391 391 391 392 392 392 393 393 394 394 394 395 395 395 396
16
Table of Contents
Active4D v5
dump request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 dump session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 a4d.debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump license info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump locals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump query params. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump request. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump session stats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a4d.json . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addArray. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addDateTime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addFunction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addRowSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addSelection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . startArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . endArray. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . startObject. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . endObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . toJSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . writep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeBoolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeDate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a4d.lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . append . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . arrayToList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . changeDelims . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . contains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . containsNoCase. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deleteAt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . find . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . findNoCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getAt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . insertAt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . len. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . listToArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 403 403 404 404 405 405 405 406 406 407 407 409 410 410 413 414 415 415 418 421 422 423 424 424 425 425 426 426 427 427 428 429 430 431 431 432 432 433 433 433 434 434 434 435 435 436 436
Table of Contents
17
Active4D v5
prepend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . qualify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . rest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setAt. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . valueCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . valueCountNoCase. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . valueList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a4d.utils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . applyToSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . articleFor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blobToCollection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blobToSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . camelCaseText . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . chopText . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collectionToBlob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deleteSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . filterCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . formatUSPhone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getMailMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getPictureDescriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getPointerReferent. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPAuthorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPAuthPassword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPAuthUser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPHost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . nextID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ordinalOf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . parseConfig. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . reverseArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sendMail. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sessionToBlob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setMailMethod. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setSMTPAuthorization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setSMTPHost. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . truncateText . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . unlockAndLoad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . validPrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . yearMonthDay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a4d.web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromArrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromLists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromOptionArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromOptionList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromRowSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . checkSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . checkboxState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collectionItemsToQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collectionToQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
436 437 437 438 438 439 439 439 441 442 442 443 443 444 444 445 446 451 452 452 453 453 454 454 455 455 455 456 456 457 459 459 461 461 462 462 462 463 464 465 466 467 468 469 470 471 472 473 473 474 475
18
Table of Contents
Active4D v5
embedCollection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedCollectionItems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedFormVariableList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedFormVariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedQueryParams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedVariables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . formVariableListToQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getEmptyFields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getUniqueID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getVariablesIterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . hideField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . hideUniqueField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . saveFormToSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . validateTextFields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . validEmailAddress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . warnInvalidField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . writeBold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Batch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Batch Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a Batch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How Batches Are Calculated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Generating Batch Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Iterating Through Rows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dumpDefaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getDefaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getStarts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . makeFuseboxLinks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . makeLinks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newFromArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newFromRowSet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newFromSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . previous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setDefaults. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Breadcrumbs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Breadcrumbs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Customizing Breadcrumbs Appearance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dumpLib. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fuseboxNew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setDivId. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setSeparator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fusebox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . An Overview of Fusebox. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why Should I Use Fusebox?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How Do I Learn Fusebox?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Active4Ds Fusebox Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
475 477 477 477 478 478 479 479 480 480 481 481 481 482 482 483 483 484 484 484 485 486 489 490 490 491 491 492 495 496 496 497 498 498 499 500 500 502 503 503 504 504 505 505 505 506 506 506 507 507
Table of Contents
19
Active4D v5
Configuring Fusebox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getURLFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . handleError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isFuseboxRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . makeURL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . postHandleError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sendFuseaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setURLFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fusebox.head. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How To Use This Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addCSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addDumpStyles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addJavascript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addJS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addMetaTag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getTitle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setTitle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RowSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Enter the RowSet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using RowSets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Subsetting Source Rows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RowSet Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Persistent RowSets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Which RowSet to Use. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . afterLast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . beforeFirst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clearPersistent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . columnCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . currentRow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dumpPersistent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . findColumn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . findRow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getColumn. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getData. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getEnd. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getPersistentList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getRow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getStart. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getTimeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gotoRow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isAfterLast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isBeforeFirst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isFirst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isLast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . maxRows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . move . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
508 509 509 509 510 510 511 511 512 514 514 515 516 517 517 519 519 520 520 521 521 523 525 525 525 527 528 528 528 529 529 529 530 530 530 531 531 532 532 532 533 533 533 534 534 535 535 535 536 536 536
20
Table of Contents
Active4D v5
newFromArrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newFromCachedSelection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newFromData. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newFromFile. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . newFromSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . persistent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . previous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . rowCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setColumnArray. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setColumnData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setRelateOne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setTimeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sourceRowCount. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timedOut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
537 538 539 540 541 546 546 546 547 547 548 548 549 549 550 550
Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tracing execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Standard Library Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a4d.console and a4d.debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Active4D Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changing the Log Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Session Editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Session Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Session Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Displaying the Session Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Session Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Active4D Debugging Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Debugging Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Filtering Console Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551 551 551 552 552 553 554 555 555 556 556 557 558 558 559
Index of Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567 ISO Language Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581 Named Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
Grouped by Function. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
Table of Contents
21
Active4D v5
Alphabetical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
22
Table of Contents
CHAPTER 1 ..............................................................
Introduction
Welcome to Active4D! You have chosen the ultimate environment for building worldclass web applications with 4D.
What is Active4D?
A dynamic web scripting environment has four layers: a TCP communications layer, an HTTP server layer, a scripting layer, and a database layer. The different layers can be pictured like this:
Scripting
HTTP Server
DB
Network communications
The HTTP server builds on top of the network layer, and the scripting layer builds on top of the HTTP server. The database is in a separate, independent layer. Active4D is both an HTTP web server and a server-side HTML-embedded scripting language and development environment. Thats a mouthful. Lets break down the sentence and look at what it means.
Chapter 1
Introduction
23
Active4D v5
3 Ease of setup: Active4D is ready to run out of the box. There is no complicated setup
needed.
3 Features: Active4D adds a wealth of advanced features like Virtual Hosting that offer
you some of the benefits of dedicated web servers like WebStar.
Server-Side
Scripting languages like JavaScript download their source code to the client browser and execute it there. Active4D, on the other hand, is executed on the server and the source code is removed before the page is sent to the client.
HTML-Embedded
With Active4D, dynamic HTML generation is directly embedded inside the HTML page. 4Ds web tag system, while providing some of the benefits of embedded scripting, still requires you to write many, many 4D methods to handle simple tasks like queries and ordering. In Active4D this is handled directly within the web page. In fact, with Active4D all of your application code can (and in most cases should) exist entirely outside of 4D itself.
Scripting Language
To generate dynamic HTML you must have a programming language. Active4D is a full 4D interpreter in a plugin. To program in Active4D you dont need to learn a new syntax or specialized tag language. In many cases you can literally copy 4D code from a method and paste it into a web page to be executed by Active4D. Active4D supports all 4D data types except for 2D arrays. It implements over 170 of the most important 4D commands, as well as almost 300 new commands which provide unmatched power and ease to your web development. Active4D also adds many often-requested extensions to the language, such as the break and return keywords, pass-by-reference, sophisticated string formatting, and associative arrays.
Development Environment
Active4D comes with a plethora of built-in debugging tools, both on the client side and on the 4D side. In conjunction with all of the other features Active4D provides, there simply is no more powerful or more productive web development environment for 4D, period. Nothing else comes close.
24
Chapter 1
Introduction
Active4D v5
An Example
Heres a simple example of what an Active4D page looks like:
<html> <body> Here are 5 good reasons to use Active4D:<br /> <% for ($i; 1; 5) writebr("It rocks!") end for %> </body> </html>
Note that the code is fully embedded in the page, and that except for the writebr command, which writes an expression to the HTML page, the embedded code is 4D code. During execution, Active4D passes HTML through to the response, executes everything inside the <% %> tags, and spits out the following:
<html> <body> Here are 5 good reasons to use Active4D:<br /> It rocks!<br /> It rocks!<br /> It rocks!<br /> It rocks!<br /> It rocks!<br /> </body> </html>
The source code has been replaced with the output of the Active4D code. You can find out more about programming with Active4D in Chapter 7, Interpreter.
3 Collecting information from forms and queries for easy access within your web
application
Chapter 1
Introduction
25
Active4D v5
3 Managing user sessions 3 Querying and manipulating data without having to write specialized 4D methods 3 Handling file uploads 3 Formatting text for output to HTML 3 Generating JSON data for use with Javascript client libraries 3 Handling character set issues Database and Protocol Support
Active4D comes with built-in support for 4Ds built-in database engine. You could, without much work, write wrapper methods for the various connectivity plugins that would allow you to work with other databases such as MySQL. In addition, you could also easily write method wrappers around the 4D Internet Commands to allow you to access other internet protocols like SMTP.
26
Chapter 1
Introduction
CHAPTER 2 ..............................................................
Installation
Installation of Active4D is a fairly simple matter and should take no more than a few minutes. First you must of course download the appropriate files from: http://www.aparajitaworld.com/site/products/Active4D/downloads.html There are four elements to Active4D:
3 Plugin: There is a single plugin archive for all platforms . 3 Shell: You must choose the appropriate shell for the environment in which you are
running Active4D. The shell acts as a conduit between the network communications layer and Active4D.
3 Documentation: You will definitely need this! 3 Demo: This 4D v11 database and web site demonstrates many of the key techniques
you will use with Active4D.
3 A docs folder with release notes and the full Active4D documentation set. 3 The Active4D plugin bundle. This plugin contains both Mac OS X (Intel) and Windows
versions of the plugin. Please consult the 4D documentation for information on where plugins may be installed.
Resource Files
Within the Active4D plugin bundle are resource files used by Active4D. These resource files are located in Active4D.bundle/Contents/Frameworks/icu.framework/Resources. The resource files are:
3 Active4D_42l.dat: Contains resources specific to Active4D. 3 icudt42l.dat: Contains resources used by ICU, a code library used by Active4D. This is
a very large file because it contains Unicode and internationalization data for every country and language in the world. The default location for these files is within the plugin bundle. They may also be placed in the <shared 4D folder>/com.aparajita/icu folder. The shared 4D folder is the parent of the folder which is returned by Get 4D folder(Licenses folder) within 4D. For the
Chapter 2
Installation
27
Active4D v5
location of this folder, please refer to the 4D documentation for the Get 4D folder command. If you decided to use the shared icu folder, both resource files must be placed there.
3 An Active4D folder with the Active4D standard libraries and configuration files. For
more information see Active4D Folder on page 28.
3 A web folder with Active4D utility scripts. For more information see Web Folder on
page 29.
Active4D Folder
This folder contains the Active4D standard libraries and config files which are used by Active4D.
3 a4d.json.a4l: A library which provides a full suite of methods for JSON (JavaScript
Object Notation) data for use with Javascript client libraries.
3 a4d.lists.a4l: A library which provides a full suite of methods for working with
delimited lists.
3 a4d.utils.a4l: A library which provides various non-web-related utilities. 3 a4d.web.a4l: A library which provides various web-related utilities, mostly for
working with forms.
3 Active4D.a4l: A special library that contains global event handlers for your
application. For more information on event handlers, see Chapter 10, Event Handlers.
3 Active4D.ini: A config file which sets most of the options in Active4D. 3 Batch.a4l: A library which provides methods for splitting large query results into
batches of rows and creating links to those batches.
28
Chapter 2
Installation
Active4D v5
3 fusebox.a4l: A library which implements the Fusebox 3 core. 3 fusebox.conf.a4l: A library in which you can configure fusebox. 3 Realms.ini: A config file which maps portions of a URL to security realms. 3 RowSet.a4l: A library which provides an implementation independent
representation of rows of data.
3 VirtualHosts.ini: A config file which provides the routing table for virtual hosts. For
more information on virtual hosts, see Virtual Hosting on page 57. For more information on the standard libraries, see Chapter 12, Standard Libraries. For more information on config files, see Chapter 3, Configuration.
Web Folder
This folder contains files that you may use in your site:
3 image.a4d: This file is an all-purpose script for dynamically loading images from the
database or from disk and optionally creating thumbnails from them. For more information, see image.a4d (script file) on page 234.
3 sed.a4d: This file is a reusable script for examining and editing sessions. For more
information, see The Session Editor on page 555.
Key Files
Active4D runs in one of several modes, depending on the license currently in force. The license is determined by a key file (or lack thereof ), which contains information about you and your license. Warning: You should always keep a backup of your key file.
Chapter 2
Installation
29
Active4D v5
The <4D shared licenses>/com.aparajita/Active4D folder. The 4D shared licenses folder is the folder which is returned by Get 4D folder(Licenses folder) within 4D. For the location of this folder, please refer to the 4D documentation for the Get 4D folder command. The Active4D.bundle/Contents/Resources folder. Warning: If you are running 4D Server as a service, the key file must be placed in the 4D licenses/com.aparajita/Active4D folder (location #1 above). Note: To place the key file in the Active4D.bundle/Contents/Resources folder on Mac OS X, right-click on the Active4D.bundle plugin and select Show Package Contents . Then navigate into the Resources folder.
If you have a key file in more than one place the first one found will take precedence.
3 The name and company of the key file purchaser 3 The license type 3 The platform for which the key is licensed 3 The IP address for which the key is licensed (only used with deployment licenses) 3 The expiration date of the keys license (keys never expire, only their licenses do) 3 An encoded serial number
You can access this information both through a 4D plugin call (A4D GET LICENSE INFO) and through the Active4D command get license info. Even easier, you can use the A4D_Prefs method in 4D to display a dialog with the license info, or use the a4d.debug.dump license info method to display license info in a web page or the a4d.console.dump license info method to display license info in the Active4D console.
Version Checking
Encoded in the serial number is the major/minor version of Active4D for which the key is licensed. If you attempt to use an otherwise valid key file with a version of 4D newer than the version encoded in the key file, the license will be temporarily downgraded. Note: Version checking does not apply to bug fix releases; i.e. versions 5.0 and 5.0.1 are considered the same version, whereas 5.1 is considered newer.
30
Chapter 2
Installation
Active4D v5
License Types
Each license has certain limitations of which you should be aware. The license types Active4D supports are: License Trial Deployment OEM Limits Times out after 8 hours of continuous use Tied to a single IP address, never times out on that address, times out after one week on another address No time or IP address limitation, requires special 4D code which ties it to a 4D structure
Timeouts
The trial license has a timeout period. When 4D has run continuously for the timeout period, Active4D becomes disabled. Thereafter any attempts to execute Active4D will return the text Active4D has exceeded its time limit. At that point 4D must be restarted to reset the timeout and enable Active4D.
Trial License
If Active4D cannot find a key file, or if the key file is incorrect in some way, Active4D operates in trial mode.
Deployment License
If Active4D finds a key file whose license type is Deployment, Active4D checks the IP address of the host machine against the IP address in the key file. If an exact match is found, Active4D operates in deployment mode with no timeout, unless the version check fails, in which case Active4D reverts to trial mode. If the host machine has more than one IP address, Active4D will check all of the hosts IP addresses for a match. On Mac OS X, only interfaces whose names begin with en (ethernet interfaces) will be checked. If an IP address match cannot be made, Active4D reverts to expired mode, which times out after one week of continuous use. Until you get a new key le, you must restart 4D once a week. Ideally you should obtain a new key le in advance if you know your application will be moved to a server with a different IP address. However, if you unable to secure a new key le before switching, this scheme allows you to operate Active4D for a full week after switching. During this time you should be able to obtain a new key le. Once you have a new key file, you must restart 4D to have Active4D run in Deployment mode once more. If you are running Active4D on 4D Server, checking the license status from a Client will indicate the license is running in expired mode, since the IP address of the Client cannot match the Server IP address.
Chapter 2
Installation
31
Active4D v5
To check the license status of a Server-based key file, you must use the a4d.debug.dump license info method, the a4d.console.dump license info method, or the get license info command on a page served by Active4D running on Server.
OEM License
For information on OEM licensing, please contact sales@aparajitaworld.com.
Installation Options
There are several installation scenarios: starting a database from scratch, installing into a non-Active4D database, and updating an existing Active4D 4.x database.
10 Copy the Active4D plugin bundle into a directory which is accessible to the target database. Please consult the 4D documentation for information on where plugins may be placed. 11 Open the shell database folder. On Mac OS X, you must right-click on the database and select Show Package Contents . 12 Open the target database folder.
32
Chapter 2
Installation
Active4D v5
13 Copy the Active4D and web folders from the shell database folder to the target database folder. 14 Open the target database in 4D. 15 In your startup sequence (On Startup, On Server Startup, or a method called by them), add a call to the method A4D_Startup. 16 In your shutdown sequence (On Exit, On Server Shutdown, or a method called by them), add a call to the method A4D_Shutdown. 17 If you want to access the Active4D preferences dialog, console, or session monitor, you will need to add menu items that call A4D_Prefs, A4D_Console or A4D_SessionMonitor respectively. 18 If you plan on using 4D Client as a web server, follow the instructions in Configuring 4D Client as a Web Server on page 36. 19 Depending on the network layer you are using (4D/NTK), there may be additional configuration to perform. See the relevant section below for instructions on what to do. 20 Restart 4D to activate your changes.
Post-Installation Configuration
Active4D uses a special housekeeping process that takes care various internal tasks, including running special code when a web session expires. By default this process is given a stack size of 128K, which should be sufficient. If you need to change the stack size, do the following: 1 2 3 4 Open the List Editor. Click on the list A4D_Config . Change the number in the item that says HousekeeperStack=128 to the amount in kilobytes that you would like to reserve for the housekeepers stack. Close the List Editor and restart 4D.
Depending on the network layer you are using (4D/NTK), there may be some extra configuration necessary if you are installing Active4D for the first time.
Chapter 2
Installation
33
Active4D v5
Create a directory called web_static in the database folder if you are web serving with 4D Server or Standalone, or in the folder <shared 4D folder>/com.aparajita/Active4D if you are web serving with 4D Client. The shared 4D folder is the directory within which the 4D licenses folder is found. You can use this directory for static content that you want to be served directly by 4Ds web server. Install the 4D Internet Commands plugin bundle in one of the plugins folders 4D searches for plugins. Open your database and then open the 4D Preferences dialog. Consult the tables below and set each of the Web options according to the values in the tables. Click OK to accept your changes, and then restart 4D.
3 4 5
Table 1: Web/Configuration Preference Pane Option Publish Database at Startup TCP Port IP Address Allow SSL for Web Server HTTPS Port Number Default HTML Root Default Home Page Non-contextual Mode Value [checked] [as necessary] [as necessary] [as necessary] 443 web_static [empty] [selected]
Table 2: Web/Advanced Preference Pane Option Use the 4D Web cache Pages Cache Size Inactive Web Process Timeout Use Passwords Value [checked] [as desired] [as desired] No passwords
34
Chapter 2
Installation
Active4D v5
Table 3: Web/Options Preference Pane Option Send Extended Characters Directly Standard Set Use Keep-Alive Connections Number of requests by connection Timeout (seconds) Value [checked] [as desired, but must match Active4D character set settings] [as desired] [as desired] [as desired]
NTKs behavior as a web server can be configured using the 4D list A4D_NTKConfig , which contains the following items: Item IP= Description Defines the IP addresses on which NTK will listen. Leaving this empty will listen on any IP address. Specifying an address such as 192.168.1.13 will cause NTK to listen only on that address. Defines the default port on which NTK will listen for HTTP requests. Defines the default port on which NTK will listen for HTTPS (SSL) requests. Number of HTTP listeners to preallocate. Stack size for HTTP listener processes in kilobytes.
By changing the numbers in the various items, you can change how Active4Ds shell sets up NTK. If you are using NTK and would like to use SSL streams, you must follow these steps: 1 2 3 Open the method A4D_InitSSLHook. Set $outCertPath, $outCertKeyPath, and $outCertPassword to the values for your SSL certificate, SSL private key, and SSL password. Close the method and restart 4D to have your changes take effect.
Chapter 2
Installation
35
Active4D v5
2 3
4 5
Pre-Execute Hook
The pre-execute hook allows you to inspect an incoming request. Within this hook you are given access to the raw request and are free to do whatever you want with it. If you decide to handle the requset yourself, you can prevent Active4D from handling the request by returning False from the hook. If you return True Active4D will handle the request normally. Note: If your aim is to inspect and possibly change the URL, a better way to do this is through the On Request event handler. For more information, see On Request on page 124. Actually, there are two pre-execute hooks. The hook you will use depends on the network layer you are using. If you are using 4Ds web server as the network layer, you will use the hook method called A4D_PreOnWebConnectionHook. This method receives a copy of the requested
36
Chapter 2
Installation
Active4D v5
URL, the request itself, and the remote address. Because the hook receives a copy of the request, any changes you make to your copy of the request will be ignored by Active4D. Note: By default, the call to A4D_PreOnWebConnectionHook is commented out to prevent unnecessary copying of the request. If you plan to use this hook, you must uncomment its call in On Web Connection. If you are using NTK as the network layer, you will use the hook method called A4D_PreStreamExecuteHook. This method receives a stream reference which you can use to read and modify the request. Since Active4D uses the same stream reference, any changes you make to the request will be used by Active4D. Note: If you want Active4D to execute a request, you must be sure to put any data you read (or a modified version thereof ) back into the stream so that Active4D will receive the entire request.
Post-Execute Hook
The A4D_PostExecuteHook method allows you to inspect and modify the response headers and response body returned by Active4D after it has executed, but before the response is sent. This method receives a pointer to the response header names and values (two parallel text arrays) and a pointer to the response body BLOB. Within this hook you may make any changes you wish to the response headers or the response body, and those changes will be reflected in the response sent to the client. If you change the response length, the Content-Length header must be changed accordingly. There is already code in the A4D_PostExecuteHook to do this, but it must be activated. If you do change the length of the response, do the following: 1 2 Locate the If (False) statement towards the bottom of the method. Change False to True.
Chapter 2
Installation
37
Active4D v5
38
Chapter 2
Installation
CHAPTER 3 ..............................................................
Configuration
Active4D ships preconfigured to meet most needs, but you can configure virtually every aspect of Active4D to fit your specific needs. Before discussing the various configuration (or config) files, you must know where to find them.
3 <Disk>:\Users\<user>\AppData\Roaming\4D\com.aparajita\Active4D\conf
(Windows 7 or Vista)
3 /Library/Application Support/4D/com.aparajita/Active4D/conf
(Mac OS X)
3 <Disk>:\ProgramData\4D\com.aparajita\Active4D\conf
(Windows 7 or Vista)
3 Active4D.bundle/Contents/Resources/conf
Note: Active4D will follow aliases and symbol links on Mac OS X and shortcuts on Windows. This arrangement allows you to have multiple versions of config files, with those earlier in the search path overriding those later in the search path.
Chapter 3
Configuration
39
Active4D v5
So, for example, you could establish a baseline set of configuration options which you keep in the shared 4D folder, then override that configuration for a particular database by putting a separate config file in <Database folder>/Active4D. Warning: If Client is being used as a web server, you must install the config files on the Client machine.
Configuration Files
Active4D has four config files: Active4D.ini, ExtensionMap.ini, Realms.ini and VirtualHosts.ini. These are plain text files which may be created and edited on any platform, as Active4D will accept Mac, Windows and Unix line endings. Default versions of these files which should suit most needs are shipped with Active4D. Each file is heavily commented, so if this documentation is not handy you can always read the comments. It is recommended that you keep a copy of the default config files somewhere safe in case you need to go back to a baseline configuration. Active4D periodically checks to see if the config files have been modified. The interval between checks is set with the refresh interval option in Active4D.ini. If a config file has been modified, it is reloaded automatically, so there is no need to quit and restart 4D to have the changes take effect. Note: The config files are loaded on startup and their locations are cached, so you may not move them without restarting the server.
3 /Library/Application Support/4D/com.aparajita/Active4D (Mac OS X) 3 <System Disk>:\ProgramData\4D\com.aparajita\Active4D (Windows 7 or Vista) 3 <System Disk>:\Documents and Settings\All Users\Application
Data\4D\com.aparajita\Active4D (Windows XP)
Path Format
All paths specified in config files must be in URL format (also known as Posix format), which has the following attributes:
3 The directory separator is / 3 A full path begins with a leading /, a relative path does not 3 A directory path may or may not be terminated with a trailing /
40
Chapter 3
Configuration
Active4D v5
3 A file path must not be terminated with a trailing / 3 The path may not contain the native directory separators : and \ 3 The path may begin with a special directory token, discussed below 3 The path may contain directory movement (../) 3 Any element of a path may be an alias or symbolic link in Mac OS X, or a shortcut in
Windows There are four tokens you may use at the beginning of a path to represent special directories. The tokens are: Token <default> <web> <4d volume> <boot volume> Directory The default directory, as defined in The Default Directory on page 40 The web root directory The name of the volume on which the 4D application resides The name of the system boot volume
The tokens include the < and >, and are replaced with the directories they represent, without a trailing /. This allows you to create paths that are portable across machines and 4D directories. For example, you may want to include files from a folder called includes outside of the web root, perhaps at the same level as the web root folder. To do so you would specify this path:
<web>/../includes
To help you understand how URL paths map to the Mac or Windows paths used by 4D, here are a few samples of full paths in 4D format and URL format, where Dev is the name of the boot volume on Mac OS X: Native Full Path Dev:site:web: Dev:site:web:index.a4d Images:02:0213.jpg C:\Dev\site\web\ C:\Dev\site\web\index.a4d D:\02\0213.jpg Native Relative Path :site:web site\web\ Platform Mac Mac Mac Win Win Win Platform Mac Win URL Path /site/web /site/web/index.a4d /Volumes/Images/02/0213.jpg /C/Dev/site/web /C/Dev/site/web/index.a4d /D/02/0213.jpg URL Path site/web site/web
Chapter 3
Configuration
41
Active4D v5
Note: On Mac OS X, full paths on the boot volume may begin either with /Volumes/<volume name>/ or just / whereas full paths on non-boot volumes , must begin with /Volumes/<volume name>/ The first time Active4D converts a . Posix path to a 4D path, the boot volume name is looked up and then cached. If you wish to rename your boot volume while 4D is running, you must restart 4D to ensure path conversions are correct.
Active4D.ini
The config file Active4D.ini controls most of the behavior of Active4D and must be in an Active4D folder in the standard search path. There are several dozen options you can set in this file. Each option is in the form: <option> = <value> Case is not significant either for keys or values, and you can have any amount of white space surrounding the = You may also use line comments and block comments just as . you would in 4D and Active4D. The options in Active4D.ini are listed below. A detailed discussion of the options can be found in the Active4D.ini file itself. Table 1: Error Handling Options Option error page http error page log level Description The root-relative URL path to a file to execute when an error occurs The root-relative URL path to a file to execute when an HTTP error occurs A sum of the bit flags defining which type of events to log
42
Chapter 3
Configuration
Active4D v5
Table 2: HTTP Server Options Option cache control default page executable extensions expires fusebox page max request size parameter mode receive timeout root serve nonexecutables Description The default cache control for executable files Name of default page when directory URL is requested File extensions which Active4D will consider executable The number of minutes before a page should expire Page through which Fusebox requests go The maximum size in kilobytes (K) of a request, including the headers Which collections to use for form variables and query string params Maximum wait time when receiving from a TCP stream Root web directory Whether Active4D should serve non-script files
Table 3: Interpreter Options Option auto relate one auto relate many output charset output encoding platform charset script timeout Description Whether to load related records in auto-related one tables Whether to load related records in auto-related many tables The character set to convert to when writing text to the response buffer The encoding to perform on text written to the response buffer The character set from which source files are converted to Unicode The minimum script timeout in seconds
Table 4: Library Options Option auto refresh libs lib dirs lib extension refresh interval Description Whether to automatically refresh libraries Extra search paths for libraries The extension for Active4D libraries How often to check libraries and config files for modification
Chapter 3
Configuration
43
Active4D v5
Table 5: Security Options Option auto create vars safe doc dirs safe script dirs Description Whether to create local variables from form variables and query params Directories allowed for document commands outside of root Script directories outside of root
Table 6: Session Options Option session cache mode session cookie domain session cookie name session cookie path session purge interval session timeout session var name use session cookies use sessions Description Where to cache sessions The domain of the session cookie The name of the cookie to store with the session ID The path of the session cookie The minimum interval in seconds between attempts to purge expired sessions The length of time in minutes that a session can live without any user interaction The name of the local variable to automatically set to the current session ID Whether Active4D should store session IDs in cookies A global switch for session management
ExtensionMap.ini
This config file maps filename extensions to MIME types. It is used primarily by Active4Ds HTTP server. For more information on this file, see ExtensionMap.ini on page 55.
Realms.ini
This config file specifies the mapping between realm names and portions of a URL that identify those realms. It is used primarily by Active4Ds HTTP server. For more information on this file, see User Authentication on page 55.
VirtualHosts.ini
This config file provides a routing table for virtual hosting, which allows you to create multiple independent web sites on the same machine. For more information on this file, see VirtualHosts.ini on page 57.
44
Chapter 3
Configuration
CHAPTER 4 ..............................................................
Security
Security is something you should worry about with any web site. When a web site has direct access to a mission-critical database, security is a mission-critical issue. Active4D provides several mechanisms to ensure your site is as secure as possible.
3 A web site is only as secure as its web server. 3 Active4D removes the source code before serving the page. Web Server Security = Source Code Security
If an attacker compromises the security of your web server, your source code is at risk but then, so is everything else on the web server, including the database. If the attacker is bent on being destructive, there are far easier and more effective ways to wreak havoc than to change the embedded source code in a web page. And it is highly unlikely that the hackers of the world know the 4D language.
Circumventing Active4D
Active4D always strips out source code before sending a page to the client. But what if the page is served directly without passing through Active4D? It is up to you to ensure that every request is passed to Active4D. If you are using 4Ds built-in web server as the network layer, there is a potential risk. Active4D is only invoked through the On Web Connection mechanism. On Web Connection is only invoked when the user requests a URL that does not exist. URLs that reference existing files are served directly by 4D without invoking On Web Connection. Warning: If 4Ds web server has its default HTML root set either to nothing or to your real web root, there is nothing to prevent a casual user from reading your source code.
Chapter 4
Security
45
Active4D v5
For example, lets suppose the user is given this URL: www.myserver.com/4DCGI/mypages/mypage.a4d Let us further suppose that this page exists within a directory called web within the database directory, and the 4D web servers default HTML root is set in the Database Properties dialog to web If the user then enters the same URL without /4DCGI like . , this: www.myserver.com/mypages/mypage.a4d 4D will directly serve that page, complete with embedded source code, without going through On Web Connection. On the other hand, if 4Ds default HTML root is set to nothing, the user could still access the source with this URL: www.myserver.com/web/mypages/mypage.a4d It is critical that you create an empty decoy directory in your database directory and set 4Ds default HTML root to that folder, then set Active4Ds root directory to something else. By doing this, you ensure that all URLs without /4DCGI will be to non-existent files, thus forcing 4D to route the request through On Web Connection and ultimately to Active4D.
Potential Attacks
Even if a miscreant does not succeed in hacking into your web server, there are still many opportunities for mischief. For an excellent essay on the security issues arising from a web-based scripting language, I recommend reading the following: http://www.securereality.com.au/studyinscarlet.txt If you do read this essay, please note that Active4D addresses almost every potential attack outlined there.
46
Chapter 4
Security
Active4D v5
If an attempt is made to execute a file outside of the root directory, this path list is checked. If the file lies within one of the specified directories, the execution is allowed to proceed. Otherwise the behavior is as specified above for unauthorized directories. By default the safe script dirs path list is empty.
3 Aborts execution of that command, but continues executing the script 3 Sets OK to zero 3 Sets the variable A4D_Error to -45 (File is locked)
As a result of this behavior, you should at least check the OK variable when using any document commands.
Chapter 4
Security
47
Active4D v5
48
Chapter 4
Security
CHAPTER 5 ..............................................................
HTTP Server
You may remember from the introduction the diagram of the various layers that make up a web scripting system. That diagram is reproduced here.
Scripting
HTTP Server
DB
Network communications
Both the HTTP server layer and scripting layer are handled fully by Active4D.
3 Network communications between the host and the client 3 Parsing of HTTP requests and obeying the rules of the HTTP protocol based on the
contents of those requests
3 Finding the resource requested and returning it in a response with the appropriate
HTTP response headers
3 Providing a means of specifying realms of the web site that require user authentication 3 Error handling 3 Virtual host routing Active4D + Network Layer = Web Server
Active4D relies on the host to provide network communications. Other than that, Active4D handles all of the task listed above, right out of the box, with no programming
Chapter 5
HTTP Server
49
Active4D v5
required. And because Active4D is the web server, you have full access to every aspect of both the HTTP request and the HTTP response from within Active4D. Believe me, implementing a web server with all of those features using other tools is not a trivial exercise! The Active4D Shell comes preconfigured to use 4Ds web server. If you already are using NTK and wish to use it with Active4D, it can be used as the network layer as well.
HTTP Fundamentals
To understand the functioning of a web server, it really pays to understand how HTTP requests work. David Adams has been kind enough to allow me to include Chapter 47 of his most excellent book, The 4D Web Companion. Before going on, I recommend taking the time to read through this excellent introduction to HTTP, which is included in the Active4D documentation distribution as a separate PDF document, HTTP Fundamentals.pdf. Note: You dont need to pay attention to his coverage of 4D web commands and tags, as you will have no need for them with Active4D.
3 Efficiency: It is inefficient to initialize and run the Active4D interpreter for a file that
has no executable code.
3 Stability: If Active4D is asked to parse a file that is not textual, such as a GIF file, it is
possible that it could be fooled into executing nonsense, which would lead to an error condition.
50
Chapter 5
HTTP Server
Active4D v5
4 5 6
7 8 9
10 If the request method is POST and the Content-Length header indicates a request size larger than the max request size option in Active4D.ini, a status of 413 (Request Entity Too Large) is returned immediately. If you are using A4D Execute Stream Request, the receive callback is called to read the rest of the response before returning the 413 response. 11 If an X-Requested-With header is present with the value XMLHttpRequest the , *ajax item in the request info collection is set to true, the content charset is set to UTF-8 and the output charset is set to A4D Charset UTF8. , Note: Every major browser and Javascript toolkit tested automatically sets this header, you should never have to worry about setting it yourself. 12 If an On Request event handler has been defined, it is called with the path portion of the URL. If the event handler returns a non-empty string, the URL of the request (not
Chapter 5
HTTP Server
51
Active4D v5
including the host) is replaced with that value. If the status has been set by the handler to anything other than 200 (OK), the request is aborted and the status is returned. For more information on the On Request event handler, see On Request on page 124. 13 If the filename of the requested URL has an extension, the extension is checked against the executable extensions option in Active4D.ini. If it matches an extension there, it is considered executable. Otherwise it is considered non-executable. 14 If the requested file is considered executable, what happens next depends on the request method. If the filename has either no extension or an executable extension and the request method is HEAD or GET nothing more is done. , If the file is considered executable, what occurs next depends on the network layer used in conjunction with Active4D.
4 5
52
Chapter 5
HTTP Server
Active4D v5
If the URL ends with /, it is assumed to be a directory. If the URL was mapped by VirtualHost.ini, the default page specified there is appended to the directory. If the URL was not mapped, the next default page in the list of default pages is appended. The full path is converted from URL to native format and any aliases in the path are resolved to their targets. The resolved target path replaces the unresolved path. The full path is checked to make sure it is either in the root directory or in one of the directories specified in the safe script dirs option in Active4D.ini. If it is not, a status of 403 (Forbidden) is returned immediately. The full path is checked to see if it is a valid directory path. If so, a trailing / is added and a redirect is issued to that URL.
7 8
10 If the full path is invalid and the request was not mapped by VirtualHosts.ini and there are more default page names to try, the server goes back to step 6. Otherwise 404 (Not Found) is returned immediately. 11 The current realm (if any) is set from the realm map in Realms.ini. For more information on realms, see User Authentication on page 55. 12 If the full path is valid, the file is opened and the interpreter is invoked to execute the file. For information on what happens during execution, see Chapter 7, Interpreter. 13 If a graphic has been written to the response buffer and the response buffer is empty, something went wrong during the graphic conversion process and the response status is set to 404 (Not Found). 14 If the status is >=400 (an error), skip to Step 21. 15 If cache-control has been set, a Cache-Control header is added to the response headers. Since older browsers do not obey the Cache-Control header, if the cachecontrol setting is no-cache a Pragma response header with the value no-cache , is added, and the expires time is set to now. 16 If a content type has been set, a Content-Type response header is added. 17 If a charset has been set, it is appended to the Content-Type response header. 18 If an expires date has been set, an Expires response header is added. 19 The headers in the response header collection are added. 20 The cookies in the response cookies collection are added as Set-Cookie response headers. 21 The X-STATUS response header is set to the response status. 22 If the request method is HEAD the response buffer is cleared. In this case, or if the , response status is less than 400 (no error), skip to Step 25. 23 If the status is >=400 (an error), Active4D attempts to find a file in the root directory with the name <status>.html, where <status> is the numeric status. Thus with a 404 (Not Found) status, Active4D would look for a file called 404.html . 24 If such a file is found, it is placed in the response buffer, and a Last-Modified response header is added. If such a file is not found and the HTTP spec says that an error message should be returned for the current status, an appropriate error message is placed in the response buffer. 25 A Content-Length response header is added which contains the size of the response buffer.
Chapter 5
HTTP Server
53
Active4D v5
26 A Content-Type response header is added with the MIME type of the response. 27 Control is returned to 4D. The shell code sends the response headers and then the contents of the response buffer. If 4D 2003 is the network layer and the ContentType response header is text/html 4D tags are stripped from the response. ,
5 6 7 8
Configuration
The Active4D web server is configured through the four config files, Active4D.ini, ExtensionMap.ini, Realms.ini and VirtualHosts.ini.
Active4D.ini
There are several config options in Active4D.ini that determine the basic behavior of the web server. For information on the format of config options, see Chapter 3, Configuration. For a detailed description of each option, see the comments in the Active4D.ini file itself.
54
Chapter 5
HTTP Server
Active4D v5
ExtensionMap.ini
When a web server sends a file to the client browser, it must inform the browser of the files type. Similarly, when a client uploads a file to the web server, the web server receives the files type. This type is sent and received as a MIME type. MIME types are standardized and can identify a files type independently of its filename extension. ExtensionMap.ini is a config file that allows Active4Ds web server to map filename extensions to MIME types. For example, let us say that Active4D receives a request for the file logo.png It looks into its extension map and finds an entry which says that the . corresponding MIME type is image/png . Details on the format of the extension map entries can be found in the ExtensionMap.ini file.
User Authentication
Active4D provides full support for protecting portions of your web site against intruders by using the basic HTTP authentication protocol. Currently authentication only works with executable files. For example, you may have an admin section of your web site that only administrators should have access to. Another section of your web site is only for accounting users. By defining realms sections of the web site defined by a hostname or substring of a requested files path you can automatically be notified when a users credentials need to be authenticated. Note: The basic HTTP authentication protocol has a number of security problems if it is not used over a secure SSL connection. In addition, each browser handles user authentication differently. Therefore it is recommended that you use your own formbased authentication if you need maximum control over the process. The user authentication mechanism requires three elements that work together:
Realms.ini
This config file specifies the mapping between realm names and substrings of a path that identify those realms. Each entry in Realms.ini has two fields in this format: Realm<tab>Match string
Chapter 5
HTTP Server
55
Active4D v5
The realm is a logical name for the section of the web site you wish to protect. It need not have any relation to an actual directory name. Realm names should not have any extended characters or spaces. If there are extended characters they are ignored. Spaces are converted to underscores. You use the realm name internally to determine what section of the web site is being accessed. The browser caches user credentials for each realm, so subsequent authorized accesses in the same realm do not result in repeated requests for credentials. If the match string begins with ? it is matched against the query string portion of the , requested URL. If any portion of the query string matches, the corresponding realm is set. If the match string does not begin with ? it is matched against the host name and the , fully resolved path of the requested URL. If any portion of the host name or path matches the match string, the corresponding realm is made the current realm. Matching is case-insensitive, but the entire match string must be found within the query string, host name or path. Note: The realm is matched to the path which results after virtual host mapping, after the default page is added to a directory request and after any aliases have been resolved. Because the match string could be anywhere in the path, you must ensure that your web directory names and match strings are selected such that the match strings do not inadvertently match the wrong directory. In addition, because the realm entries are scanned in order, realms cannot be nested. For example, you may not put the directory admin in the admin realm and the subdirectory admin/accounting in the accounting realm. Only one of them will ever be selected. If a realm is matched and the On Authenticate event handler has been defined, it is called before execution begins to allow you to authenticate the user. If the match string is not found, there is no current realm and the authentication mechanism is not invoked. Lets look at some example Realm.ini entries. `Realm secure-server admin Match string www.myserver.com /admin/
The first entry would place the entire host www.myserver.com in the realm www.myserver.com That means any request made on that server would have to be . authenticated for that realm. The second entry places the directory admin in the admin realm. Note the use of the leading and trailing slashes to ensure only a directory is matched in the path. Dont worry if the user enters www.myserver.com/admin, because Active4D redirects that to www.myserver.com/admin/ which will match correctly.
56
Chapter 5
HTTP Server
Active4D v5
Virtual Hosting
If you create a large database in 4D, most likely it has more than one module. Often these modules are restricted to a certain set of users. When bringing a database to the web, you will want to carry the same structure to your web site. You could accomplish this by directing the different classes of users to separate subdirectories within the root directory. But wouldnt it be nice to have completely separate web sites for each one? Virtual hosts allow you to host more than one web site on a single machine and a single instance of 4D. Each virtual host can be mapped to a different web root and/or different default page.
VirtualHosts.ini
This config file specifies a routing table which determines where Active4D should route HTTP requests. The criteria is uses to determine the routing are:
3 hostname: This would be used if the client enters a domain name in the URL, such as
www.active4d.net.
3 IP address: This would be used if the client enters a direct IP address in the URL, such
as 192.168.1.7.
3 language: This would be used if you have partitioned a single domain/IP address into
separate sites based on the preferred language the client has specified in the browser. The language is specified as an ISO language code. A complete list of codes can be found in ISO Language Codes on page 581. Since this is a routing table, you must specify the target of the routing. The complete format for a virtual host entry consists of a line with five tab-delimited fields: IP Address[:port]<tab>Hostname[:port]<tab>Language<tab>Root|Host<tab>Default
There may be any number of tabs between fields. Line and block comments may be used between entries as well. The target of a given routing is specified by two fields:
3 Root|Host: The Root|Host field may contain two values separated by | (vertical bar).
If this field does not contain | the entire contents of the field is used to specify the , web root. If the field contains | the portion to the left of the | specifies the web root, , and the portion to the right of the | specifies the virtual host name. The web root portion should be a URL-style (Unix) path. If it is relative (not beginning with /) it is relative to the default directory (see The Default Directory on page 40). You may use any of the path tokens (such as <4d volume>) that are valid for the root option in Active4D.ini, or you may use * (without quotes) to use the value of the root option in Active4D.ini. The virtual host name portion can be any text (including spaces). The specified name is available through the *virtual host item in the request info collection. This is useful,
Chapter 5
HTTP Server
57
Active4D v5
for example, if you are using common templates for each virtual host but skinning them individually. You can use the virtual host name as a means of building a path to images and stylesheets for each virtual host.
3 Default: This field specifies the filename of the page that should be used as the
default page (when a directory is requested) for the given virtual host. Using * (without quotes) will use the value of the default page option in Active4D.ini. You may use a value of * in the IP Address, Hostname and Language fields to ignore that field when matching. The entries are searched in order, so they should progress from most specific to the least specific. Hostname matching is case-insensitive and Language matching is casesensitive. Both the IP Address and Hostname fields accept standard 4D wildcard characters to allow partial matches. Otherwise the entire field must match. An invalid or missing value will result in that entry being ignored. The Hostname field must include the port if the host is on a port other than 80. The final entry in the table should be terminated with a line ending. If a match is made with the IP Address, Hostname, and Language fields, the Root|Host and Default fields are used to set the web root, virtual host, and default page.
The first entry routes all requests where the users browser is configured with French as the preferred language. The directory web_fr is made the root directory for those requests, the virtual host name is set to fr and a URL to a directory will redirect to the , default file defaut.a4d in that directory. The second entry will route all requests to mac.home.com. The root directory and default file will be set to whatever they are configured to be in Active4D.ini. The virtual host name will be main . The third entry will route all requests to the virtual host mac.admin.com. The root directory will be set to admin the virtual host name will be admin and the default file , , will be set to whatever it is configured to be in Active4D.ini.
58
Chapter 5
HTTP Server
Active4D v5
The fourth entry will route all other requests to the IP address 192.168.1.7 in the same way the second entry does. For completeness, you should always have an entry for both the hostname and IP address to catch all possible requests. The fifth and sixth entries route all requests to the host mac.home.fr or the IP address 192.168.1.27. The directory web_fr is made the root directory for those requests, the virtual host name will be fr and a URL to a directory will redirect to the default file , defaut.a4d in that directory. The final entries route requests to the domain foo.com or to the subnet 192.168.2 to the web root web_foo The virtual host name will be empty. .
3 X-Error-Status: This header contains the HTTP error status code. 3 X-Error-URL: This header contains the full requested URL that caused the error. Customizing the Error Handling
You can override the default HTTP error message in several ways:
3 http error page: If you set the http error page option in Active4D.ini, Active4D will
attempt to execute that page if it is executable or load it statically if not. If you have not specified anything in the http error page option, or you have and the page cannot be found or an error occurs during its execution, Active4D moves on to the next option.
3 <status>.html: The next option is to attempt to find a static HTML file called
<status>.html in the current web root directory, where <status> is the HTTP status code. If found, it is served statically. If it is not found, Active4D returns the default (but very friendly) error message. For example, to show a custom error page for a 404 (Not Found) error, simply create an Active4D page and name it 404.a4d then place it in the root directory. When a 404 error , occurs, Active4D will execute your custom page. Note: If you use an executable HTTP error page to handle 401 Unauthorized, which is the error status returned by the authenticate command, make sure the execution of the error page does not trigger another call of authenticate.
Chapter 5
HTTP Server
59
Active4D v5
60
Chapter 5
HTTP Server
CHAPTER 6 ..............................................................
Invoking Active4D
If you are just starting to use Active4D, the Active4D shell provides everything you need to get up and running without the need to understand the details of the plugin API. If you are using the shell as is, you may safely skip this chapter. If on the other hand you are integrating Active4D with your existing web server code, you will need to understand the plugin API.
Types of Execution
There are two different ways of executing scripts in Active4D: request execution and direct execution. Request execution requires that you pass a valid HTTP request to Active4D. The request body contains the embedded script. Direct execution requires only that you pass the embedded script to Active4D, although you may optionally pass a query string as well.
Request Execution
Once the host web server receives HTTP request, you pass the request to Active4D through one of the A4D Execute <type> request commands. They are: A4D Execute BLOB request A4D Execute 4D request A4D Execute stream request
Chapter 6
Invoking Active4D
61
Active4D v5
A4D Execute <type> request(<inRequest>; inRequestInfo; outHeaderNames; outHeaderValues; outResponse) Longint Parameter <inRequest> inRequestInfo outHeaderNames outHeaderValues outResponse Result Type Varies Array Text Array Text Array Text BLOB Longint Description Request or means to retrieve it See below Response header field names Response header field values Response body HTTP status code
Discussion The array parameters must be text arrays, otherwise an error is generated. The inRequestInfo array provides Active4D with context information not available in the HTTP request itself. It has a very specific format as follows: Element 1 2 3 4 4DK# Name A4D Request Remote Addr A4D Request Host Addr A4D Request Host Port A4D Request Secure Description IP address of client (browser) IP address of server on which request was made Port on which request was made 1 if SSL request, 0 if not
Examples of how to initialize this array are contained in the shell database methods On Web Connection and A4D_HTTPD_RequestHandler (NTK shell). The <inRequest> portion of the parameter list changes depending on the command used. The parameters before the common parameters listed above are summarized in the following pages. After handling a request, Active4D returns everything necessary to create a proper HTTP response in the last four parameters. The actual contents of those parameters depends on whether or not the request executed successfully and what happened during execution. outHeaderNames/outHeaderValues If Active4D is given a request to an executable file, these parallel arrays receive the HTTP response headers. The headers returned for an executable file are as follows: In addition to these headers, you can set response headers within Active4D with the set response header command.
62
Chapter 6
Invoking Active4D
Active4D v5
Name X-VERSION X-STATUS Content-Type Content-Length Cache-Control Pragma Expires Location Set-Cookie WWW-Authenticate
Notes Always HTTP/1.1 always first element , Always second element. See Result on page 64 for possible values. The MIME type of the file The size of the response body (outResponse) See RFC 2616 section 14.9 Automatically added with the value no-cache if Cache-Control is no-cache . Unless explicitly set within Active4D, is set to the current time to prevent response caching If a redirect is performed If a session is created and session cookies are enabled, or if a cookie is set within Active4D If the authenticate command is used
If Active4D is given a request to an non-executable file and is configured to serve nonexecutables, the following headers are returned: Name X-VERSION X-STATUS Content-Type Content-Length Last-Modified Notes Same as above Same as above Same as above The size of the file, which is in outResponse The files last modified datetime in HTTP format
If Active4D is given a request to an non-executable file and is not configured to serve non-executables, outResponse is empty and the following headers are returned: Name Path ModDate ModTime Notes Full native path to the file Modification date of file in MM DD YYYY Forced format Modification time of file in HH MM SS format
Given this information, the host web server can easily serve the file. For example, using 4Ds web server you could call DOCUMENT TO BLOB followed by SEND HTML BLOB. Using NTK you could call TCP Send File.
Chapter 6
Invoking Active4D
63
Active4D v5
The modification date/time are returned to allow the host web server to implement a caching mechanism. outResponse This parameter will always contain the response body. The actual contents depends on the context: Context Executable file, successful execution Contents The result of the execution
Executable file, error occurred Variable, see Chapter 7, Interpreter, for more info Non-executable file, no If-Modified-Since header passed in Non-executable file, If-Modified-Since header passed in The requested file (if it can be found)
If the file can be found and it has not been modified since the time passed in, the response body will be empty. Otherwise the response body will contain the requested file.
Result The status code returned by Active4D will be one of the following: Code 200 301 302 303 304 Name OK Moved Permanently Found See Other Not Modified Description All is well A permanent redirect has been performed in response to a request from an HTTP 1.1 client A redirect has been performed in response to a request from an HTTP 1.0 client A redirect has been performed in response to a request from an HTTP 1.1 client A non-executable file is being served and the client passed an If-Modified-Since header and the file has not been modified since that time The request is malformed in some way You used the authenticate command Either Active4D has timed out or an attempt was made to execute a script outside of the safe script directories The requested resource could not be found One of the callbacks returned an error during execution of A4D Execute stream request The request size limit has been exceeded An unrecoverable error has occurred during execution
Not Found Request Timeout Request Entity Too Large Internal Server Error
64
Chapter 6
Invoking Active4D
Active4D v5
Code -1 -2
Description A non-executable file was requested and the server non-executables option is off The continuous execution time period for the current license has expired
Active4D takes care of creating the proper response headers and response body for each status code.
version 2
Discussion This command expects the entire request (including uploaded files) to be in the inRequest parameter. It could be used with NTK if you retrieve the entire request into a BLOB first. If 4D is running in Unicode mode, the contents of inRequest are assumed to be stored in the format UTF8 Text without length. Note: If you are using NTK, I recommend using A4D Execute stream request instead of this command, as it performs a two-stage retrieval and relieves you of having to retrieve the request.
A4D Execute 4D request(inRequest; inRequestInfo; outHeaderNames; outHeaderValues; outResponse) Longint Parameter Type inRequest Text <standard params> Result Longint Description HTTP request HTTP status code
Discussion This command is designed for use with 4D built-in web server. It expects the header of the request to be in the inRequest parameter. For posted forms, the body of the request is retrieved through the A4D_GetHttpBodyCallback method. If you want to change the callback method, call A4D Set HTTP body callback.
Chapter 6
Invoking Active4D
65
Active4D v5
version 2
A4D Execute stream request(inStreamRef; inRequestInfo; outHeaderNames; outHeaderValues; outResponse, outReqInfoNames; outReqInfoValues) Longint Parameter inStreamRef <standard params> outReqInfoNames outReqInfoValues Result Type Longint Array Text Array Text Longint Description TCP/IP stream reference Receives request header names Receives request header values HTTP status code
Discussion This command is designed for use with an NTK-based web server. It does all the work of receiving the request from the TCIP/IP stream referenced by inStreamRef. It does so in two stages, first retrieving and parsing the request header, then retrieving the body if necessary. A4D Execute stream request returns request info in the two parallel arrays outReqInfoNames and outReqInfoValues. The content of those arrays is as follows: Name *request method *http version *url <HTTP header> Value GET or POST 1.0 or 1.1 The requested URL without query string <HTTP header value>
The first three elements are a parsed version of the first line of the HTTP request. From the fourth element on are the HTTP headers of the request, URL-decoded and converted to Unicode. These arrays are provided to allow you to do custom post-processing of a request without having to parse it yourself. If you have no need for this information, you can simply not pass outReqInfoNames and outReqInfoValues. Note: If Active4D is unable to read the request header, outReqInfoNames and outReqInfoValues will be empty. Setting the Stream Callbacks Before using this command you must call: A4D Set stream callbacks(inReceiveMethod)
66
Chapter 6
Invoking Active4D
Active4D v5
The parameter is a string which contains the name of the callback method used by Active4D to retrieve the request from the TCP/IP stream. Note: The callback method must be in the host database, not in a component. The signatures of the callbacks are as follows:
ReceiveCallback
ReceiveCallback(inStreamRef; inStopString; inMaxLen; inTimeout) BLOB
version 2
TCP/IP stream reference Receiving stops at this Maximum bytes to receive Maximum ticks to wait Received data
Discussion All of the parameters are passed in according to the rules of the NTK command TCP Receive Blob. Basically, you shouldnt have to worry about how this method works, since a receive callback method is provided for you in the shell. If the receive fails for some reason, the callback must place a single longint with the value zero in the result BLOB.
Chapter 6
Invoking Active4D
67
Active4D v5
Direct Execution
In addition to executing HTTP requests, there are also a set of commands that allow you to directly execute a file or to execute a block of text: A4D Execute file A4D Execute text A4D Execute BLOB With these commands you do not have access to most of the HTTP context information like cookies, form variables, etc., since there is no HTTP request to parse.You can, however, pass in a query string.
Discussion This command executes the file given by inPath as embedded Active4D code, just as if the file were being served as a web page. If inPath begins with /, it is considered an absolute path. If inPath does not begin with /, it is considered relative to the default directory. For information on the default directory, see The Default Directory on page 40. For more information on the format of inRequestInfo, see the discussion of inRequestInfo in A4D Execute <type> request on page 62.
68
Chapter 6
Invoking Active4D
Active4D v5
A4D Execute text(inText; inQuery; inRequestInfo; outHeaderNames; outHeaderValues; outResponse) Longint Parameter inText inQuery inRequestInfo outHeaderNames outHeaderValues outResponse Result Type Text Text Array Text Array Text Array Text BLOB Longint Description Text to execute Query string Execution context Response header field names Response header field values Response body HTTP status code
Discussion This command executes the text given by inText as embedded Active4D code, just as if the text were being served from a web page. For more information on the format of inRequestInfo, see the discussion of inRequestInfo in A4D Execute <type> request on page 62.
version 3.0
A4D Execute BLOB(inText; inQuery; inRequestInfo; outHeaderNames; outHeaderValues; outResponse) Longint Parameter inText inQuery inRequestInfo outHeaderNames outHeaderValues outResponse Result Type BLOB Text Array Text Array Text Array Text BLOB Longint Description Text to execute Query string Execution context Response header field names Response header field values Response body HTTP status code
Discussion This command executes the text given by inText as embedded Active4D code, just as if the text were being served from a web page. It as assumed that the text is stored in the BLOB with the format UTF8 Text without length. For more information on the format of inRequestInfo, see the discussion of inRequestInfo in A4D Execute <type> request on page 62.
Chapter 6
Invoking Active4D
69
Active4D v5
70
Chapter 6
Invoking Active4D
CHAPTER 7 ..............................................................
Interpreter
Much of the power of Active4D lies in its language. Unlike 4Ds semi-dynamic HTML tags, which are a transmogrified subset of the 4D language, Active4Ds language is a superset of 4Ds language. In other words, with Active4D you just write 4D code. In fact, in some cases you can write and test code in 4D and then paste it into a text editor to use with Active4D. Active4Ds interpreter is actually quite a bit stricter than 4Ds, in that syntax errors and nonsensical constructions that 4D blithely ignores (but the compiler catches, of course) are considered errors and abort execution. Active4D extends 4Ds language in some important ways. In addition to defining new operators, you can also define methods and libraries of methods. These are covered in Chapter 8, Methods.
Flow of Execution
The Active4D interpreter is essentially a text processor. It parses text input (which might be a file or a block of text) and writes to a response buffer. The text input may have any mixture of HTML and embedded Active4D source code. When execution begins, the response buffer is empty.
Input Parsing
Lets look at an extremely simple example which will illustrate how Active4D parses and executes a script. Suppose we execute a file which has the following contents:
<html> I was here at <% write(current time) %> on <% write(current date)%> </html>
Chapter 7
Interpreter
71
Active4D v5
Active4D begins execution by scanning for a source code begin tag. As it scans, the text is appended to the response buffer. When the first <% in the above example is reached, the response buffer contains:
<html> I was here at
Once a source code tag is found, Active4D skips past the tag and goes into execution mode. In execution mode, Active4D continues to parses the text, but instead of passing the text through to the response buffer, it resolves the text into executable tokens and then executes the tokens. It would be pretty useless if you could not write dynamically generated text to the response buffer within your source code, so Active4D provides a write command to do just that. The write command takes a value of any type, converts it to text, and appends the result to the response buffer. In the example above, the write command is the first token. The write command handler is given control, which proceeds to evaluate the parenthesized expression following the command. In this case the expression is the 4D command Current time, which is converted to text as if passed to the String command. The text is appended to the response buffer, and the interpreter then continues parsing. The next token is %> which is a source code end tag. Active4D skips to the end of the , tag and switches back to scan mode. At this point the response buffer contains:
<html> I was here at 19:27:13
The interpreter scans up to the next source code begin tag, appending to the response buffer. At the start of the next source code block, the response buffer contains:
<html> I was here at 19:27:13 on
The interpreter then executes the second source code block as it did the first, after which the response buffer contains:
<html> I was here at 19:27:13 on 10/19/2001
The interpreter scans to the end of the file and returns control to the caller. At that point the response buffer contains:
<html> I was here at 19:27:13 on 10/19/2001 </html>
If the interpreter was invoked by Active4Ds web server, the web server generates the HTTP headers necessary to describe the response to the client. Finally, control returns to
72
Chapter 7
Interpreter
Active4D v5
4D, and the shell sends the generated headers and response body to the client browser, which displays the text: I was here at 19:27:13 on 10/19/2009 The client cannot see the source code because it is stripped out before being sent back from the server.
Language Syntax
For the most part Active4Ds language (henceforward just Active4D) has the same syntax as 4Ds language. However, there are a few important differences and enhancements.
English Only
When you write code in 4Ds method editor, 4D looks up the command names and named constants in localized resources within the 4D application. For example, in English you might type query to do a database search, but in French the command name is chercher . After looking up a command or named constant, 4D stores a universal token to represent it. If you open the same method in different language versions of 4D, the tokens are displayed in the localized language. Because Active4D code is written in raw text, it exists on disk in the form it was written. Hence no localization can be done, so all Active4D code must use the English 4D commands and named constants.
Since you can use whitespace in your code, it is highly recommended that you take advantage of the opportunity and get used to doing so.
Chapter 7
Interpreter
73
Active4D v5
You can have any number of Active4D code blocks within an HTML page. In addition, it is not necessary to complete control structures within the block in which they are declared. This powerful feature allows constructs like this:
<% for($i; 1; 3) `I'm starting the loop here... %> Active4D rocks!<br /> <% end for %> `Here is Active4D Active4D Active4D the output rocks! rocks! rocks!
Using this feature with If/Else/End if, you can conditionally show entire tables, form items, etc. Note: Just because your source is embedded inside your web pages in text form does not make it inherently insecure. To understand why, please see Chapter 4, Security.
Case Sensitivity
Like 4D, Active4D is not case sensitive, so you can just as easily write first record as FIRST RECORD But whereas the 4D method editor would change first record to FIRST . RECORD when it parsed the line, in Active4D it will remain first record because you will be using an external text editor. Case-insensitivity extends to table and field names, method names, and variable names.
Expression-based
One difference between 4Ds language and Active4D is that Active4D is expressionbased, like most computer languages. In other words, everything is an expression, including an assignment. So the assignment:
$i := 10
actually evaluates to the value of $i after the assignment, namely 10. This allows you to do convenient tricks like this:
first record([contacts]) while (($name := [contacts]lastname) = "a@") writebr($name) next record([contacts]) end while
74
Chapter 7
Interpreter
Active4D v5
Comments
Active4D supports regular 4D comments (indicated by `), either on a separate line or at the end of the line, with no limit on their length. You may also use the characters // as a synonym for ` to indicate a 4D-style single-line comment. This style of commenting is common to C++, Java, and Javascript. Personally I prefer these comments to 4D-style comments, not only because Im a longtime C++ programmer, but also because they are much more visible than tiny little backticks. In addition to line comments, Active4D supports block comments. Unlike line comments, block comments may be embedded within a line or may span multiple lines. Block comments begin with the character sequence /* and end with the character sequence */ For those of you who know other languages, this is the standard syntax for . block comments in C/C++, Java, CSS, etc. Active4D also supports line continuation comments. Line continuation comments are indicated by \\ and are the same as normal comments, except that they logically join the line on which they occur with the following line, allowing you to break a single line of code into multiple lines.
Chapter 7
Interpreter
75
Active4D v5
Identifiers
Identifiers in Active4D follow the same stated rules as in 4D in terms of length and valid characters, with the following exceptions:
3 The general rules for valid characters are the same, but the specific rules for valid
Unicode characters can be found here:
http://java.sun.com/j2se/1.3/docs/api/java/lang/Character.html#isJavaIdentifierStart(char).
3 The maximum length for local variables, Active4D method names and library names is
255 characters.
76
Chapter 7
Interpreter
Active4D v5
least, all 4D 2004 and v11 named constants are available. If a 4D 2004 named constant was renamed in v11, both the old and new names are available.
Data Types
Active4D can operate on all 4D data types except for 2D arrays. Data types may be implicitly converted according to the same rules 4D uses, or explicitly converted using commands such as String and Num.
Compiler Declarations
All compiler declarations are supported, and may be used for local, process, and interprocess variables. For more information on declaring process and interprocess variables, see Process/Interprocess Variables below. Active4D extends the 4D compiler declaration syntax by allowing you to use any valid scalar (non-array) expression, including dereferenced pointers and collection items. The collection item need not exist, in which case it will be created. By predeclaring local variables with compiler declarations, you can achieve better type safety in your code. For example:
c_longint($long) $long := 7 $long := 13.27 /* Without the compiler declaration, $long would become a real = 13.27. Because it was declared a longint, its value is now 13. */ $long := "foobar" `generates an incompatible argument error
Active4D imitates 4Ds interpreted behavior exactly in regards to variables that have been declared in compiler declarations. Once a variable has had its type fixed by a compiler declaration there are two ways it can be changed:
3 With another compiler declaration. If the new type is not assignment-compatible with
the old type, the variable will be set to a null value. Otherwise a type conversion is done.
3 By passing it as a parameter to a command that sets the parameter value inline, such
as GET PICTURE PROPERTIES.
Chapter 7
Interpreter
77
Active4D v5
Process/Interprocess Variables
You may use compiler declarations to create process or interprocess variables on the fly, even in a compiled database. However, if your database is compiled, you may not change the type (or string width) of an existing process or interprocess variable. Warning: Although you may create and reference process/interprocess variables within Active4D, you may not pass a pointer to those variables to 4D in a compiled database. In addition to using compiler declarations, process and interprocess variables can be created on the fly through assignment, just as local variables are. For example, this works fine, even in a compiled database:
foobar := 7 get field properties(->[foo]bar; fieldType)
Of course, you should have a compelling reason to use process or interprocess variables instead of local variables. Basically, there are two main reasons for using process or interprocess variables in Active4D:
3 You need to pass an array to a 4D method. 3 You are using the execute in 4d command to execute 4D code, and the code needs to
receive or return values. If 4D is running in Unicode mode, there are no restrictions on process/interprocess variable usage. If 4D is running in compatibility mode, the following rules apply:
3 Text variables/arrays are read write, whether they are declared in 4D or in Active4D. 3 String variables/arrays appear to Active4D as text variables/arrays. 3 If you declare a process/interprocess string variable/array in 4D, it is read only within
Active4D.
Array Support
All array types except 2D arrays are fully supported in Active4D. This includes picture and pointer arrays. You may declare and use arrays in Active4D just as you would in 4D. In most cases you should use local arrays, unless there is a compelling need to use process or interprocess arrays. Note: Active4Ds array support is dramatically expanded beyond that provided by 4D. You should take the time to carefully read the command section Arrays on page 137.
78
Chapter 7
Interpreter
Active4D v5
Pointer Support
Active4D supports pointers to process and interprocess variables, tables, and fields. You may create and dereference pointers to any of these entities within Active4D. As in 4D, you may not create a pointer to a local variable. However, Active4D allows you to pass local variables by reference to its own methods, which is effectively the same as using a pointer (but easier). For information on pass by reference, see Chapter 8, Methods.
Note: Extended boolean expressions can only be used with commands and keywords that take a boolean expression, not the logical operators & and |.
Literals
Active4D recognizes string, number date and time literals in all the standard formats except scientific notation. Note: Time literals must use '?' as the delimiter.
Chapter 7
Interpreter
79
Active4D v5
String Literals
Like 4D, all strings literals support backslash-prefixed embedded control characters: Backslash combination \n \r \t \" \' \\ Resolves to Char(Line feed) Char(Carriage return) Char(Tab) Char(Double quote) Char(Quote) \
If you have not yet gotten used to using backslashed characters, you should definitely get used to using them instead of the equivalent Char(X) expression. Here is an example of using backslashes in a literal, with the equivalent Char(X) code. You decide which is easier to write and read.
write("This is line 1.\r\"It's cool!\", you say.") Output: This is line 1. "It's cool!", you say. // Pre-4D 2003 code to do the same "This is line 1."+Char(13)+Char(34)+"It's cool!"+Char(34) \\ +", you say."
However, there is a better way to embed double-quotes in a string literal. Active4D also supports string literals surrounded by single quotes, within which double-quotes are just another character. So the example above becomes:
write('This is line 1.\r"It's cool!", you say.')
String Interpolation
How many times have you had to write a line of code like this:
writeln("Name: " + [contacts]name + " (" + $formattedPhone + ")"
We are used to writing code like this, so it may seem normal. But the problem is that all of the + operators obscure the actual format of the string you are trying to write. Wouldnt it be nice if you could do something like this:
writeln('Name: [contacts]name ($formattedPhone)')
80
Chapter 7
Interpreter
Active4D v5
Now it is very clear what the final string will look like. The good news is that you can do exactly what is shown above. There is an additional property of single-quote delimited strings that adds a very powerful feature. This features is called string interpolation. Basically, what string interpolation means is that the string is parsed for embedded values and those values are replaced within the string. The types of embedded values recognized are:
3 Built-in collections: References to values in the _form, _query, _request, globals and
session collections.
3 Field references: Full [table]field references. If the field name contains spaces, it must
be treated as an expression.
Chapter 7
Interpreter
81
Active4D v5
Note in the example above that we referenced a longint. All types that can be converted to text are automatically converted. If you try to embed a variable expression that is not convertible to text, it will generate an error. What if we want to embed a collection reference? Again, no problem:
$info := new collection("name"; "Dave"; "age"; 27) array string(31; $info{"children"}; 0) set array($info{"children"}; "Jody"; "Buffy") writebr('Name: $info{"name"}, age: $info{"age"}') for ($i; 1; size of array($info{"children"}) writebr('Child: $info{"children"}{$i}') end for write('First letter of name is "$info{"name"}[[1]]"')
Basically, you can embed any valid variable reference, with an optional character reference at the end. What happens if the variable or field name or _form/_query/_request reference is followed or preceded by valid identifier characters? How do we distinguish between the embedded reference and the surrounding text? In a case like this you have to enclose the expression in backticks (`), like this:
$verb := "sleep" write('Are you $verbing?') write('Are you `$verb`ing?')
82
Chapter 7
Interpreter
Active4D v5
In actual fact, anything enclosed in ` ` is evaluated as an Active4D expression, as if you were assigning the result of the expression to a variable. This allows you to embed arbitrary expressions, like this:
write('It is `current time` on `string(current date; long)`.')
You can use anything in the expression, including method calls, but the expression must return a result or an error will be generated. If you need to use one of the reserved characters within an interpolated string, simply prefix it with a backslash to prevent it from being interpolated, like this:
$amount := 100 write('You owe me \$$amount.') // output is "You owe me $100."
Heredoc Strings
Active4D also allows you to define strings literals that span multiple lines. Such string literals are known as heredoc strings. A regular heredoc string begins and end with the character sequence """ (three double quotes). An interpolated heredoc string begins and ends with the character sequence '''(three single quotes), and is interpolated as described above for interpolated strings. As with interpolated strings, the big advantage of heredoc strings is clarity: in your code you can see multi-line strings as they will appear in the final output. Here is an example:
$cell := ''' [Contacts]Firstname [Contacts]Lastname<br /> [Contacts]Address<br /> [Contacts]City, [Contacts]State [Contacts]Zip<br />''' writeln($cell) // output will be something like this: Homer Simpson<br /> 123 Main St.<br /> Springfield, MO 12345<br />
Heredoc allows you to do complex multiline formatting in a very natural style, with all of the power of interpolated strings if you so desire.
Date Literals
Date literal parsing is more rigid than in 4D. Dates must contain three parts consisting of digits, separated by a forward slash, space, dot or dash.
Chapter 7
Interpreter
83
Active4D v5
Time Literals
Time literals may use spaces as separators in addition to colons, and each part of the time (hours/minutes/seconds) may contain a single digit.
User-defined Constants
In addition to supporting 4D named constants, Active4D allows you to define named constants at runtime using the define command. For more information on the define command, see define on page 217.
Typing of Values
Typing of local variables in Active4D follows the same rules as 4D. If a local variable has not been declared with a compiler directive, it is variant: its type changes on the fly according to the type of value assigned to it. Once it has been declared within a compiler declaration, it follows the rules outlined in Compiler Declarations above. On the other hand, 4D variables and fields are always considered invariant. You cannot assign a value to them that would change their type. For all variables and fields, Active4D will generate an error and abort execution if a referenced variable or field is undefined.
Operators
Active4D implements all of 4Ds operators (with the exception of some picture operators), including array indexing and character references. Active4D operators have the same restrictions on the data types they will accept as 4D does. Active4D will abort with an error if an attempt is made to divide or modulo by zero.
Unary/Assignment Operators
Active4D adds many unary and assignment operators (borrowed from other languages) which make writing code faster and easier to read. Here are the new operators: ++ -+= -= *= %= /= \= ^= |= prefix and postfix increment prefix and postfix decrement add and assign subtract and assign multiply and assign modulo divide and assign divide and assign integer divide and assign exponentiate and assign bitwise inclusive OR and assign
84
Chapter 7
Interpreter
Active4D v5
bitwise AND and assign bitwise shift left and assign bitwise shift right and assign
is equivalent to:
<assignable> := <assignable> <op> <value>
Any of these operators will work with array elements. So, for example, you can increment the fifth element of an array by using the ++ operator:
$myArray{5}++ ++$myArray{5}
Chapter 7
Interpreter
85
Active4D v5
In general, every time you say to yourself, Is this value (not) in that sequence, you can use the ~ and !~ operators. The examples below demonstrate how to do in matching using the ~ operator and the equivalent code using PO4D (Plain Old 4D):
if ($name ~ $contactNames) // using ~ if (find in array($contactNames; $name) > 0) // PO4D if ($sub ~ $text) // using ~ if (position($sub; $text) > 0) // PO4D if ("b_cancel" ~ $attributes) // using ~ if (collection has($attributes; "b_cancel")) // PO4D
Using these operators is exactly equivalent to using the regex match command:
// this... if ($name =~ "/(Dave|John|Bill)/") // ...is the same as this if (regex match("/(Dave|John|Bill)/"; $name)) // and this... if (not($name =~ "/(Dave|John|Bill)/")) // ...is the same as this if ($name #~ "/(Dave|John|Bill)/")
For more information on regular expression matching, see regex match on page 253.
86
Chapter 7
Interpreter
Active4D v5
For more information, see %% (formatting operator) on page 332. The % operator has three meanings in Active4D:
3 If it is preceded by a number, it means modulo division, just as it does in 4D. 3 If it is preceded by a text expression, it follows the same syntax as the %% operator.
For more information, see % (formatting operator) on page 331.
Picture Operators
Active4D supports horizontal and vertical concatenation for pictures. Thus the operators that may be use with pictures are: + / += /= horizontally concatenate vertically concatenate horizontally concatenate and assign vertically concatenate and assign
+ Operator
The + operator has been enhanced in Active4D to auto-convert arguments to text if the argument one of the arguments is text. For example:
$s := "I was here at " + current time + " on " + current date
Notice there is no need to explicitly convert Current date and Current time to strings. The argument to the left of the + will also be converted to text if the argument to the right is. For example, this will work:
$s := current date + ", " + current time + ": I was here"
Chapter 7
Interpreter
87
Active4D v5
Format 4D default 4D default 4D default 4D default True or False ->[table] ->[table]field ->variable
Indexing Operator {}
Active4D extends the syntax of array indexing in two convenient ways. First, there is a super easy way to add elements to an array. If you use an empty index with an array, a new element is appended to the array and the index is set to the newly appended element. This allows you to add items to an array in a very simple way, like this:
array longint($longs; 0) $longs{} := 7 // same as append to array($longs; 7) $longs{} := 13 // same as append to array($longs; 13) // $longs now contains 2 elements, 7 and 13
88
Chapter 7
Interpreter
Active4D v5
This syntax works anywhere you can use an array element, not just as the target of an assignment. For example, you can do things like this:
array longint($types; 0) $table := table(->[vendors]) for ($field; 1; count fields($table)) get field properties($table; $field; $types{}) end for // $types is now filled with the [vendors] field types
The second extension to the array indexing syntax is the addition of negative indexes. By using a negative index, you index array elements from the end of the array, with -1 being the last element and -Size of array being the first element. For example, to reference the last element of an array, you can simply do this:
$myArray{-1} := 7 // old way, which one is easier? $myArray{size of array($myArray)} := 7
Boolean Operator |
The boolean | operator may be used with text. If the operand on the left is empty, the expression resolves to the operand on the right, else to the operand on the left. This is useful for avoiding the common idiom:
if ($attributes{"nm"} = "") $foo := "Some default value" else $foo := $attributes{"nm"} end if // using choose $foo := choose($attributes{"nm"} # ""; $attributes{"nm"}; \\ "Some default value")
The above code can now be replaced with the much clearer and more concise:
$foo := $attributes{"nm"} | "Some default text"
Control Structures
All of 4Ds control structures and flow of control keywords are supported, with four notable additions: for each/end for each, break, return, exit and continue. If you are familiar with other languages that use these keywords, they work exactly as they do in those languages. If are arent familiar with those languages, heres how they work.
Chapter 7
Interpreter
89
Active4D v5
break
If you are within any kind of loop (For, for each, While, Repeat), the break keyword (used on a line by itself ) will transfer execution to the first line of code after the end of the loop. The loop variable used by a For loop will not be changed. If you use break outside of a loop it will generate an error.
return
This keyword (used on a line by itself ) transfers execution to the first line of code after the current code block. If you are within an Active4D method, execution will continue at the first line of code after the line that called the method. If you are within an included file, execution continues after the include statement that included that file. return can also take a parenthesized expression to return as the result of the method.
continue
If you are within any kind of loop (For, for each, While, Repeat), the continue keyword (used on a line by itself ) will transfer execution directly to the top of the loop.
3 The loop variable in a For loop will be incremented according to the For clause. 3 The next item will be fetched in a for each loop.
If you use continue outside of a loop it will generate an error.
exit
This keyword, used on a line by itself, immediately aborts all execution without generating an error. This is primarily useful for debugging, when you want to dump the internal state before a certain point and then stop. This keyword is also useful if you have detected an error condition from which you cannot recover and you want to immediately stop execution.
90
Chapter 7
Interpreter
Active4D v5
Examples
Here are some examples of how to use the new keywords:
// Using break to terminate an infinite loop $i := 0 while(true) // You could never do this in 4D! if (++$i > 10) // The closest loop, in this case the while loop, // will be exited break end if write($i) // This will NOT be executed once break is executed end while // Here's the Active4D way of breaking out of a for loop for ($i; 1; size of array($names)) if ($names{$i} = "g@") break end if // This will not get executed after break is executed writebr($names{$i}) end for // Here's the 4D way for ($i; 1; size of array($names)) if ($names{$i} = "g@") $i := size of array($names)+1 else writebr($names{$i}) end if end for // Using continue in a for loop for ($i; 1; size of array($names)) if ($names{$i} = "s@") continue // Immediately goes to next iteration of loop end if writebr($names{$i}) // Do lots of other stuff here. // The effect of continue above is to skip this end for
Chapter 7
Interpreter
91
Active4D v5
3 4D document commands: As with 4D, in Active4D absolute paths are relative to the
computer, allowing you to access any volume mounted on the host machine (including network volumes). Remember, however, that by default Active4D restricts document command access to the web root directory. You must use the safe doc dirs option in Active4D.ini to gain access to directories outside the web root directory. For more information, see The safe doc dirs Config Option on page 47. As with 4D, relative paths are relative to the default directory (see The Default Directory on page 40).
3 Active4D commands: Active4D commands are designed for use within the context
of a web page. Thus their world, so to speak, is limited to the web root directory. Absolute paths used with Active4D commands are relative to the web root directory. Thus if the root directory is: /Users/tom/db/web the path /accounting/default.a4d is actually the path /Users/tom/db/web/accounting/default.a4d Relative paths used with Active4D commands are relative to the directory of the currently executing file.
Path Utilities
Active4D provides a many utility commands for working with paths. For example, if you need to use a 4D document command on a file within the web root directory, the get root command returns the full path to the current root. In addition, there are commands to extract the filename from a path, the extension from a filename, and the directory
92
Chapter 7
Interpreter
Active4D v5
from a path. If you need to join path segments together, you can (and should) use the join paths command. For more on these commands, see System Documents on page 354.
Path Limits
The host operating system imposes a maximum length on paths and components of a path. On Mac OS X the maximum length of a single component of a path (file or folder name) is 255 bytes. The maximum length of a path is 1024 bytes. Note that these limits are in bytes, not Unicode characters, and that paths are encoded in UTF-8. Non-ASCII characters in a path will take 2-4 bytes each, reducing the maximum number of Unicode characters accordingly. On Windows the maximum length of a single component of a path (file or folder name) is 255 Unicode characters. The maximum length of a path is 260 Unicode characters. You must ensure that your path lengths are within these limits, or Active4D will not be able to find your files.
3 Factoring out common page elements, such as headers and footers. When the
included file is modified, all pages that include it automatically update.
3 Separating functional sections of a page into separate files. This allows you to create a
page design that consists of an overall framework, within which you plug in various
Chapter 7
Interpreter
93
Active4D v5
pieces. By using includes, you can edit the pieces separately without affecting the overall design. This technique is analogous to splitting a large method into several smaller methods.
3 Using include into to build an HTML page to send via email. Including Only Once
You can also include files using the require command. The require command works like include, but it guarantees that any given file will only be executed once via require within a single execution of the interpreter. The require command is primarily useful for creating files of global constants, variables and methods that only need to be loaded once per Active4D session. All files that reference these globals can require the globals file and you don't have to worry about the overhead of executing the file or the problem of defining named constants twice, which is an error.
Calling 4D Methods
Although you can call 4D methods within Active4D, this ties you to the database structure, which is exactly what Active4D is designed to avoid. If possible, you should define and use methods within Active4D. For more information on defining methods in Active4D, see Chapter 8, Methods. Nonetheless, should you need to, you can call any 4D method within Active4D using the exact same syntax you would within 4D.
Parameter Passing
When calling a 4D method from Active4D, you pass parameters just as you would within 4D. Strings are converted to Text and Longints are converted to Reals before being passed. You may return any type of value from the method. Warning: If you are passing textual parameters to a 4D method from Active4D, the parameter in 4D must be declared C_TEXT. If you are passing numeric parameters, they must be declared C_REAL. Otherwise a runtime error may occur in a compiled database. Active4D has no way of matching parameters passed to a 4D method with the actual parameters declared in that method. It is up to you to make absolutely sure that the number and type of parameters declared in the 4D method are compatible with what you pass to it. If the 4D method expects some parameters to be optional, you may of course not pass those.
94
Chapter 7
Interpreter
Active4D v5
In an interpreted database, if the method parameters are not assignment-compatible, 4D will initialize the parameter to a null value. In a compiled database, however, if the parameter types do not match exactly, a runtime error will be generated, which will effectively bring your application to a halt in a very unfriendly way. You do not want this to happen.
The method name may be any valid expression that returns text. This powerful feature allows you to dynamically determine which of several methods you call, as long as their parameter lists are compatible. This is (sort of ) the equivalent of a method pointer in other programming languages. As with ordinary method calls, the method called by call 4d method may return a value. If the 4D method returns a value, you may ignore it if you have no use for it. You need not assign it to a dummy variable as you would in 4D. On the other hand, if the 4D method returns no value, attempting to use the result of such a method will result in an error.
Collections
Active4D adds a new data type to the language: collections. A collection is a group of key/value pairs which are stored in memory. The keys are strings (with a maximum length of 2GB) and the values may be any 4D data type, including arrays. The key/value pair is also referred to as an item. In classic programming terms, a collection is also known as an associative array, a dictionary, a symbol table or a map. In 4D terms, you can conceptually think of a collection as two parallel arrays, with keys being in one array and the values in the other. Of course, you cant do this in 4D because 4D arrays can only contain a single type, and a collection value may be of any type. Active4D provides a full suite of commands for creating your own collections. In addition, Active4D uses collections to store HTTP headers, query parameters, form variables, cookies, global variables, and sessions. For more information on the collection commands, see Collections on page 149.
Collection Handles
Collections are referred to by a Longint handle, much like an ObjectTools object handle or a 4D hierarchical list handle.
Chapter 7
Interpreter
95
Active4D v5
Active4D maintains an internal list of user-created collections. All collection commands that take a collection handle check the handle against this list and generate an error if the handle is not valid. Thus you are prevented from crashing the server by passing in a bogus handle.
Using Collections
Collections come in two basic varieties: read-only and read-write. You can perform the following operations with read-only collections:
3 Get a collection value given a key. If the value is an array, you may retrieve an element
of the array directly. Key matching is case-insensitive.
3 Get all keys into a 4D array. 3 Get all values into a 4D array if it is known they are all of the same type. 3 Get the count of key/value pairs in the collection.
Read-write collections add the following operations:
3 Set a collection value given a key. If the value is an array, you may set an element of the
array directly.
3 Delete a collection item given a key. If the key contains a wildcard, all matching items
are deleted. In addition to these basic operations, some of the specialized collections defined by Active4D provide other operations as well. These operations are covered in the relevant command reference sections.
96
Chapter 7
Interpreter
Active4D v5
where collection is either a collection handle or collection iterator, and key is a text expression. If an item in the collection exists with the given key, the result of this expression is the items value, and it may be treated in all respects as a variable of that type. If no item exists in the collection with the given key, the result of the expression is an empty string. Because the result of the expression is treated as the value it resolves to, you can use collections as a natural part of the language. For example:
// Set a counter in our session session{"counter"} := 0 // Now increment the counter ++session{"counter"} // Store a form variable in the session session{"username"} := _form{"f_username"} // Embed an array in a collection $c := new collection array text($c{"people"}; *; "Tom", "Dick", "Harry") for ($i; 1; size of array($c{"people"})) writebr('Hi $c{"people"}{$i}') end for $c{"people"}{} := "Louise"
Embedded Collections
You can embed collections in collections (by storing their handles) to any depth and reference their items by adding more indexes, like this:
$foo := $c{"level1"}{"level2"}{"level3"}{"the_key"}
You may safely embed global collections within a local collection, because the global collections will outlive the local collection in which they are embedded. On the other hand, you must embed only global collections within other global collections to ensure the embedded collection is valid throughout the lifetime of the containing collection.
Element Referencing
If when referencing a collection array element, you use the form:
collectionRef{key}{index}
If the item is in fact an array, you may use any value from 0..size of array for the index. If the item is scalar (not an array), you may still use the index form above, but the index must evaluate to 1.
Chapter 7
Interpreter
97
Active4D v5
This form allows you to reference a collection item with the same syntax whether or not it is an array. This feature is mainly designed for use with multiple-choice form lists, which may result in a scalar value (if only item is selected) or an array value (if multiple items are selected).
3 The iterator itself (a Longint) is zero 3 is an iterator will return False 3 get item key will return an empty string 3 get item value will return an empty string 3 get item type will return Is Undefined (5)
You can identify an empty iterator either by testing equal to zero, by calling is an iterator, by testing for an empty key, or by testing the item type. For more information on iterators, see Iterators on page 208.
Request Data
As was discussed in Chapter 5, HTTP Server, an HTTP request consists of several headers and an optional body, in addition to the requested URL itself. The data encapsulated in an HTTP request includes:
98
Chapter 7
Interpreter
Active4D v5
If you have never gone through this process, heres a little tip: the time it takes to do Step 1 alone will cost you more than the price of Active4D! Fortunately Active4D does all of the above for you. You never have to deal with the particulars of the HTTP specification, which allows you to focus on the problem at hand building a great web site.
Likewise, to access a query string parameter called recnum you could use: ,
_query{"recnum"}
Chapter 7
Interpreter
99
Active4D v5
clicked by checking for empty strings. For example, your code would look something like this:
case of :(_form{"f_search"} # "") // Do the search :(_form{"f_previous"} # "") // Go to the previous group of records :(_form{"f_next"} # "") // Go to the next group of records end case
Response Data
You control the response body indirectly with the write command and its peers. In addition, Active4D gives you dedicated commands for setting the response headers. The data encapsulated in an HTTP response includes:
3 Cache control 3 Character set 3 Content type 3 Cookies 3 Expires date 3 Other headers
Some HTTP response headers are simple in their format. Others require a specific format which you must follow. As with the request headers, without Active4D you would have to know the HTTP specification for each format. For those headers that require special formatting, Active4D gives you simple commands that relieve you of having to know the HTTP specification.
3 Executable source files: These may be in any charset, but if you are working with a
non-Asian language, it is recommended you use UTF-8.
3 Database: 4D uses Unicode internally and expects text to be in this charset. 3 URL query strings: Query strings are URL-encoded UTF-8. 3 Posted form data: Form data is URL-encoded in the charset of the page in which the
form appears.
3 Files read programmatically: Text files may be in any charset. It is up to you to know
which one. In each case, text must be converted to Unicode.
100
Chapter 7
Interpreter
Active4D v5
3 Web browser: Text sent to the browser via the write commands should be in the
target HTML charset, usually UTF-8. In addition, you may need to HTML-encode reserved characters such as <.
3 Database: 4D expects Unicode. 3 Files written programmatically: You can use whatever charset you want.
Clearly, it would be a real pain not to mention error-prone if you had to remember to do all of the character set conversions yourself. Fortunately, Active4D allows you to configure the various charsets and then takes care of most of these conversions for you. Internally Active4D uses Unicode, since that is what 4D expects and because it allows Active4D to work with any character set on Earth. The character sets you configure determine which charset Active4D converts from on input and which charset it converts to on output.
Chapter 7
Interpreter
101
Active4D v5
You can set the output charset with the output charset config option in Active4D.ini. The possible options are the same as for the platform character set. You may also use the set output charset command. The default output charset on Japanese language systems is shift_jis The default . output charset on Chinese language systems is gb2312 The default output charset on . all other systems is iso-8859-1 . Note: The default iso-8859-1 charset may change to utf-8 in the future, so it is recommended that you convert your source files to UTF-8 as soon as possible
Output Encoding
The output encoding determines how Active4D converts special characters to HTML character entities when text is written to the response buffer. Output encoding is performed before the output character set conversion, since the encoding tables are based on Unicode. You can set the output encoding with the output encoding config option in Active4D.ini. You specify one or more bit flags to indicate which characters to encode. More than one flag can be specified by separating them by + and any number of spaces. The bit flags are none quotes tags ampersand extended html and all (without , , , , , the quotes). Note that extended and html are synonymous. You may also use the set output encoding command at runtime. For more information on output encoding, see set output encoding on page 277. The default output encoding on Japanese or Chinese language systems is none The . default output encoding on all other systems is html . Text is HTML encoded according to the following rules:
3 If a character is ASCII, has a named entity, and the current encoding mode asks for that
entity to be encoded, it is encoded.
102
Chapter 7
Interpreter
Active4D v5
The charset name at the end should match the charset name you use in the output charset config option. In the example above the output charset is utf-8 . This is critical for two reasons:
3 The browser must know how to interpret non-ASCII characters in the page in order to
correctly display them.
3 When a form is posted, the browser encodes the form data in the character set of the
page in which the form appears. There is unfortunately no mechanism within HTTP to communicate the character set of posted form data to the server. So Active4D must assume that the posted data is encoded in the output character set. Therefore it is critical that you use a Content-Type meta tag that matches your output character set.
Error Handling
Active4D goes to considerable lengths to catch errors and display meaningful error messages. If any errors occur during the execution of an Active4D program, execution is immediately aborted and the error handler takes over. For complete information on error handling within Active4D, see Chapter 14, Error Handling.
Script Timeout
Despite our best intentions, sometimes our scripts may do bad things like going into infinite loops or waiting an inordinate amount of time for a shared resource. Every script is given a set amount of time to execute. Before executing each line, Active4D checks to see if the timeout has been reached, and if so it generates an error and aborts execution. You may set the script timeout with the script timeout config option in Active4D.ini. The value set with this option is the minimum script timeout in seconds and is the default value for all subsequent script executions. The actual timeout can be set higher within Active4D with the set script timeout command. This command will affect the next execution of Active4D, not the one in
Chapter 7
Interpreter
103
Active4D v5
which the command is used, and in no case can it be set lower than the minimum value set in Active4D.ini.
104
Chapter 7
Interpreter
CHAPTER 8 ..............................................................
Methods
As you build your web site with Active4D, you will undoubtedly come across chunks of code that can be reused in many different contexts, just as you would reuse code in 4D. Fortunately, Active4D has a powerful system for defining its own methods.
Defining Methods
The simplest way to define a method in Active4D is to declare it inline with the rest of your code, then reference it sometime later in the flow of execution. Inline methods live only as long as the current invocation of Active4D. This means that you incur a small performance penalty each time the method is used, because it has to be parsed and stored in temporary memory before it can be used. In general, you will only want to use inline methods during testing and debugging, because there is a much better way of defining and using methods: libraries. Libraries have many advantages over inline methods and allow you to group many methods together into one logical unit. They are covered completely in the next chapter, Libraries.
Method Declaration
Whether a method is defined inline or in a library, the syntax for declaring a method is the same:
method "<name>" {({&}$arg1{=expression} {...{&}$argN{=expressionN}})} <statements> end method
I know this looks complex, but it is actually quite simple. Keep reading.
Method Name
The method name must be a double-quoted literal string which follows the rules for 4D method names in terms of allowable characters. The maximum length of an Active4D method name is 255 characters. The double-quotes are necessary to allow you to include spaces as part of the method name, and to differentiate the method name from the method keyword.
Chapter 8
Methods
105
Active4D v5
Note that there is currently no facility in Active4D for passing a variable number of parameters. You can simulate this technique by:
3 Passing a reference to an array and accessing the elements of the array 3 Passing a collection and accessing collection items by name 3 Using default parameters, which are covered in the next section
Most of the time default parameters provide the best solution, so you should try to use them wherever possible.
Method Parameters
Parameters to Active4D methods differ from 4D method parameters in several important ways.
Parameter Type
There is no typing of parameters, as they are simply local variables with a variant type. This means you can pass values of different types in the same parameter, as long as the use of the parameter in the method would not cause any type incompatibilities. If you want to ensure a parameter is of a particular type, you would have to test its type within the method using the Type command.
106
Chapter 8
Methods
Active4D v5
Here is an example of how you can take advantage of the variant parameter typing:
method "writeMany"($inValue; $inHowMany) for ($i; 1; $inHowMany) writebr($inValue) end for end method writeMany("Hello world!"; 3) writeMany(7.13; 2) // The output: Hello world! Hello world! Hello world! 7.13 7.13
Scope
Parameters passed to an Active4D method become a local variable within the scope of the method. Thus, like local variables in 4D, they have no existence outside of the method body.
method "paramTest"($inParam) $inParam:="bar" // The global $inParam is still "foo" writebr($inParam) end method $inParam:="foo" writebr($inParam) paramTest($inParam) writebr($inParam) // The output: foo bar foo
Likewise, local variables defined outside of an Active4D method cannot ordinarily be referenced within the method.
method "localTest" write($local) // This generates an 'unknown identifier' error end method $local := "foobar" localTest
Chapter 8
Methods
107
Active4D v5
Note that the global keyword means just what it says: it looks for the named variables in the global scope. If the variable you want to reference was declared within another method, you must use global before declaring or first assigning that variable, which forces it into the global scope, like this:
method "outer" global($foo) $foo := "bar" inner end method method "inner" global($foo) write($foo) // writes "bar" end method
Pass by Reference
Normally, parameters passed into Active4D methods are passed by value. In other words, the expression passed into the given parameter is evaluated and the constant value resulting from the expression is assigned to the parameter. In addition to pass by value, Active4D also allows you to pass by reference. This powerful feature is activated by prefixing a parameter in the method argument list with an ampersand (&).
108
Chapter 8
Methods
Active4D v5
Reference parameters are essentially pointers to the entity that was passed into them. You can pass 4D pointers into Active4D methods, but there are two important ways in which reference parameters are unlike 4D pointers:
3 You need not explicitly dereference the parameter to access the underlying value 3 You can pass local variables by reference
Any entity that is assignable including variables, fields, array elements, collection items and character references may be passed by reference. You can even pass a character reference to an array element by reference! Here is some examples of passing by reference:
method "paramTest"($inByValue; &$ioByReference) ++$inByValue ++$ioByReference end method $byValue := 7 $byReference := 7 paramTest($byValue; $byReference) // At this point $byValue still = 7, but $byReference = 8 method "showArray"(&$inArray) for ($i;1;size of array($inArray)) writebr($inArray{$i}) end for end method array longint($longs; 0) set array($longs; 7; 13; 27) showArray($longs) array text($names;0) set array($names; "Tom"; "Dick"; "Harry") showArray($names)
As you can see, the combination of 4D pointer support (mainly for tables and fields) and pass by reference allows you to write highly generic, reusable code within Active4D.
Default Parameters
In 4D, method parameters are numbered. Thus it is easy to pass a variable number of parameters. In Active4D, parameters are named, so there is another technique for passing variable number of named parameters. This technique is called default parameters and is another feature of Active4D borrowed from other languages. To create a default parameter, append the parameter name with = and any expression which is valid at the point of method declaration. The expression is evaluated once when the method is first parsed, and the expressions value is stored with the method parameter. Within a default parameter expression, you can reference variables, methods, named constants, etc., as long as they are valid at the point of declaration.
Chapter 8
Methods
109
Active4D v5
Here is an example:
method "showArray"(&$inArray; $inDelimiter="<br />\n") writeln(join array($inArray; $inDelimiter)) end method showArray($myArray) showArray($myArray;", ") // each element is on a separate line // elements are comma-delimited
In the first call to ShowArray, the $inDelimiter parameter is not passed, so Active4D uses its default value of <br />\n In the second call to ShowArray, the $inDelimiter parameter . was passed, so the passed value is used. This is how you would have accomplished the same thing in 4D:
C_POINTER($1) C_STRING(255;$2) If (Count parameters < 2) $2:="<br />\n" End if `And so on
Returning Values
To return a value from a method, use the return keyword, like this:
method "concatStrings"($inFirst; $inSecond) return ($inFirst + $inSecond) end method
The return keyword can also be used without a value, but if you return a value the expression must be enclosed in parentheses. Whether or not you return a value, the return keyword will immediately exit the method, no matter where in the method it occurs. This allows you to quickly exit a method when a termination condition is reached, much as the break keyword allows you to immediately exit a loop. It turns out this is extremely useful, as it saves you from having to set some kind of success flag which you test after the loop.
110
Chapter 8
Methods
Active4D v5
Here is an example:
method "findFirstOver"(&inArray; $inCompare) for ($i; 1; size of array($inArray)) if ($inArray{$i} > $inCompare) return ($i) // The method terminates and returns $i end if end for // We only get here if the loop completes without a match return (-1) end method
Chapter 8
Methods
111
Active4D v5
112
Chapter 8
Methods
CHAPTER 9 ..............................................................
Libraries
It is common for programmers to continually build up their own set of utility methods which they can call upon when needed. In 4D, these methods can be grouped together either by a name prefix or by placing them in a component. In Active4D, you can group methods together into a named logical unit called a library. The library in effect serves as both the component and the name prefix.
3 <Disk>:\Users\<user>\AppData\Roaming\4D\com.aparajita\Active4D\lib
(Windows 7 or Vista)
3 /Library/Application Support/4D/com.aparajita/Active4D/lib
(Mac OS X)
3 <Disk>:\ProgramData\4D\com.aparajita\Active4D\lib
(Windows 7 or Vista)
3 Active4D.bundle/Contents/Resources/lib
Note: Active4D will follow aliases and symbol links on Mac OS X and shortcuts on Windows. Because Active4D will follow the entire search path, you can structure your libraries in a hierarchy, from the most specific to the most general, by placing them at various points in the search path. In addition, you can specify a list of library folders to search in the config file. For more information, see the documentation for the lib dirs setting in the sample Active4D.ini config file.
Chapter 9
Libraries
113
Active4D v5
Library Definition
Libraries are special files that can only contain the following entities:
3 import keyword 3 define keyword 3 library keyword 3 end library keyword 3 Method definitions 3 Comments
Any methods within a library file must be enclosed by a library/end library pair. The library keyword must be followed by a literal string which gives the name of the library. The library name must match the name of the librarys definition file, minus the file extension. Libraries may not be nested. Note: The names Active4D and global are reserved and may not be used as library names. Here is an example library file called mylib.a4l:
library "mylib" define(kMyConstant; 7) method "myMethod"($inMyParam) writebr($inMyParam) end method method "myConcat"($inText1; $inText2) return ($inText1 + $inText2) end method end library
Importing Libraries
To use the methods in a library, you must first import it. Importing can happen in several ways:
3 Implictly during startup if the library is a circuit library. For more information on circuit
libraries, see Circuit libraries and initializers on page 508.
114
Chapter 9
Libraries
Active4D v5
1 2
Checks to see if the named library is already loaded into memory. If it has been nothing more is done. If the library is not in memory, the library search path is followed to find a file called <lib>.<ext>, where <lib> is the library name in a full <library>.<method> call or the library name passed to the import command, and <ext> is the currently configured library extension. For information on the library search path, see Library Search Path on page 113. If the library file is found, it is parsed. Active4D strips out all comments and empty lines, storing only the body of each method along with information about the method parameters. In addition, if any constants are defined in the library, they are stored as well. If the library is parsed successfully, Active4D looks for a method in the library called __load__ If it exists, it is executed. . If no errors occurred up to this point, the library name is added to a list of imported libraries. If any of the above steps fails, an error is generated and execution is aborted, unless * is passed as a second parameter to the import command, in which case a Boolean is returned to indicate the success of the import.
4 5 6
If you read the above steps closely, you will notice the following advantages that libraries have over inline methods:
3 Libraries are only loaded and parsed once during the life of the server (unless you
modify or explicitly unload them). Inline methods are loaded and parsed every time their page is executed.
3 Comments within an inline methods page must be parsed every time. Comments and
empty lines in a library are not stored. Thus you may liberally comment library methods with no performance penalty.
3 The methods in a library are scoped to the librarys name, whereas inline methods are
global in scope. See the next section for more on this.
Import Configuration
Active4D follows a standard search path when attempting to locate a library during import. If you wish to put your libraries in a directory other than one in the standard search path, you may add the directory to the lib dirs path list in Active4D.ini. By default the lib dirs path list is empty. When importing a library, by default Active4D appends .a4l to the library name and searches for a file with that name. If you wish to use a different extension for libraries, you may change it by setting the lib extension option in Active4D.ini. The extension must be a dot followed by no more than five alphanumeric characters.
Import Errors
When parsing a library, if Active4D encounters a error in the syntax of the methods definitions, it generates an error message with the location and type of syntax error. If the library is imported as part of an executable request, a standard Active4D error
Chapter 9
Libraries
115
Active4D v5
message is generated. If the library is being reloaded asynchronously during a refresh, the error message is logged.
Automatic Re-Import
Active4D periodically checks to see if the source file for each imported library has been modified. The interval between checks is set with the refresh interval option in Active4D.ini. If a librarys source file has been modified, it is re-imported automatically, so there is no need to quit and restart 4D to have the changes take effect. Note: Once a library is imported you cannot move its source file to another location without explicitly flushing the library or restarting the Active4D server.
Library Namespace
Methods and constants defined in a library are stored in memory under the librarys name. The library name then becomes a namespace that encapsulates all of the methods defined within it. This allows you to define method names without worrying whether another developer has chosen to use the same method name. As long as they are in libraries with different names, you can access each method separately.
Name Resolution
When Active4D encounters a non-4D method name, it first searches all of the imported libraries for a method with that name. If there is more than one match, an error is generated and execution is aborted. If there is one and only one match that method is executed. If two or more libraries are imported that have a method with the same name, you must disambiguate the method name by prepending the library name and a dot before the method name. Otherwise Active4D will stop and tell you that there is an ambiguous reference to a local method. For example, suppose you have these two libraries:
library "foo" method "doSomething" return ("Hello from foo") end method end library library "bar" method "doSomething" return ("Hello from bar") end method end library
116
Chapter 9
Libraries
Active4D v5
Library scope
Methods and constants defined within a library may be referenced anywhere within that library without using the library.entity syntax. In fact, all entity names within a library take precedence over names external to the library. This rule leads to the following type of problem:
method "showArray"(&$inArray) `Do something here end method `Imagine the following is within a separate library file library "myUtils" method "showArray"(&$inArray) `Do something here end method method "showArrayAndSomethingElse"(&$inArray, $inSomethingElse) showArray($inArray) `This will call myUtils.showArray() write($inSomethingElse) end method end library
In this example, the library method showArrayAndSomethingElse calls the method showArray. Because showArray is defined within the library, that version of the method takes precedence over the inline showArray method defined outside the library.
Chapter 9
Libraries
117
Active4D v5
Going back to the example above, to ensure the method showArrayAndSomethingElse calls the global method showArray, you would write it like this:
method "showArrayAndSomethingElse"(&$inArray, $inSomethingElse) global.showArray($inArray) `Calls the inline showArray() write($inSomethingElse) end method
Private methods
If a library method becomes overly long and complex, you may wish to split it up into several smaller methods. Or there may be several methods within a library that share common code and you want to factor the common code into a separate method. However, you dont want these helper methods to be publicly accessible outside the library as they have no use by themselves. You can make a method private to its library by prefixing the method name with an underscore(_). Any attempt to call such a method from outside its library will result in an error. For an example of this technique, you can examine the newFromX RowSet library methods, which use several private helper methods.
Library-private collections
In addition to private methods, libraries also are provided with a private collection in which to store library-private data. This collection is created automatically when a library is loaded during import and is cleared when a library is unloaded. Note: Because the library-private collection is in effect global in scope, if you want to store another collection within it, it must be a global collection, and you must be sure to clear that collection in the librarys __unload__ method. The library-private collection is accessed through the keyword self, which returns a handle to the collection. The self keyword may only be used within a library method. Attempting to use it outside of a library method will generate an error. For examples of how to use self, see Library Initialization/Deinitialization. Because library-private collections cannot be accessed from outside the library, you may want to provide a debugging method like the following to view self:
method "dumpData" a4d.debug.dump collection(self; \\ current library name + ": self"; \\ true) end method
118
Chapter 9
Libraries
Active4D v5
Library Initialization/Deinitialization
There are two special methods you may define within your libraries: __load__ and __unload__. If present, the __load__ method is executed when a library is loaded during import. If present, the __unload__ method is executed when a library is unloaded during a flush (either from a direct command or as part of a refresh). In conjunction with the self collection, these methods allow you to turn libraries into completely self-contained components. For example, it is very common for a database to have lists of options that need to be presented as HTML lists on a page. In many cases these lists are static, or they come from the database but change very infrequently. In such cases you can cache the pre-built HTML option lists in a library that provides methods to return the option lists. Here is what such a library might look like:
// Menus library for ORM project library "orm.menus" method "__load__" _loadAll end method method "_loadAll" _loadStates _loadCountries _loadStatuses end method method "_loadStates" self{"states"} := "" array string(2; $codes; 0) array string(31; $names; 0) split string(a4d.web.kUS_UnsortedStateCodes; ";"; $codes) split string(a4d.web.kUS_SortedStateNames; ";"; $names) for ($i; 1; size of array($codes)) $opt := '<option value="$codes{$i}">$names{$i}</option>\n' self{"states"} += $opt end for end method // and so on for the other _load methods method "getStateMenu"($inCode) $value := 'value="$inCode"' return (replace string(self{"states"}; $value; \\ $value + " selected")) end method
Note the use of a private _loadAll method, which actually does the loading. The reason for providing such a method is to enable the site administrator to reload the librarys
Chapter 9
Libraries
119
Active4D v5
cached data through the web by executing a library method from a web page. For example, we could add the following method to the above library:
method "reload" _loadAll end method
Because we factored the loading logic into _loadAll, neither __load__ nor reload will have to change if the loading logic changes.
The most important change is the call to _unload in the __unload__ and reload methods, which ensures the global collection self{"status"} is cleared.
120
Chapter 9
Libraries
Active4D v5
because they encapsulate private data, and you can call methods on these objects with an object-oriented style syntax. To create a Poor Mans Class, follow these steps: 1 2 3 4 Create a library (we will use Foo in this example) that will act as the class. Make one or more constructor methods (newFoo, newFooFromBar, etc.). In the process of construction you create a collection which becomes the "object". Make sure the collection has an item called "__class__" whose name matches the library name. It is best to use the current library name command for this. If you want the objects data to be private which you should, as good objectoriented design dictates you should force data access to go through methods prefix the key names with an underscore, which prevents them from being accessed outside of the objects library/class. So, for example, if the newFromBar constructor took a bar parameter, you would store it like this:
$object{"_bar"} := $inBar
5 6
Return the collection handle to the caller from the constructor, that is the object reference. To define object methods, define methods with a first parameter called $self, which will receive the object reference (which is actually a collection handle). For example:
method "setBar"($self; $inBar) $self{"_bar"} := $inBar end method method "getBar"($self) return ($self{"_bar"}) end method
Given an object reference, you can call a method on that object using the dereference operator (this syntax is taken from C++/PHP), like this:
$foo := Foo.newFromBar("foobar") write($foo->getBar) $foo->setBar("barfoo")
When Active4D sees ->, it transforms: $object->method(params) internally into: $object{"__class__"}.method($object; $params)
Chapter 9
Libraries
121
Active4D v5
Limitations
There is a reason these are called Poor Mans Classes Real classes have inheritance, real . constructors, destructors, and so on. In traditional terms, this technique is actually objectbased programming, not object-oriented programming. Someday in the future we will have real classes and objects in Active4D, but for now this technique is quite sufficient to implement many object-oriented techniques into your applications. For good examples of Poor Mans Classes, take a look at the source code for RowSets and Breadcrumbs, both of which use this technique extensively.
122
Chapter 9
Libraries
CHAPTER 10 ..............................................................
Event Handlers
In the course of executing a script, there are well-defined points at which a developer would like have some control. Active4D recognizes special event handler methods which are executed before and after various events. To be activated, these event handler methods must be defined in a special library called Active4D.<lib> which must reside in an Active4D directory. The , <lib> extension must be whatever you have configured the library extension to be in the Active4D.ini file. By default the library extension is .a4l . As with the config files, you may have multiple copies of the Active4D library in different directories in the search path. An Active4D library at the beginning of the search path will override one later in the search path.
On Application Start
This handler is executed when 4D first starts up or after the Active4D server has been restarted. This handler is analogous to the On Startup database method in 4D. The only Active4D collection you have access to in this handler is the globals collection. In addition, you can reliably read the following variables: Variable <>A4D_HostAddr <>A4D_HostPort Description IP address of host on which Active4D is running Port on which web server is listening
Chapter 10
Event Handlers
123
Active4D v5
On Request
This handler is executed just before the Active4D HTTP server handles a request, before Active4D parses the request URL. The handler is passed the path portion of the URL. The _query collection (or _form collection if parameter mode is set to form variables in Active4D.ini) is populated with the contents of the requests query (if any), and is set to read-write mode so that you can directly modify the query. Within the handler, there are several actions you can take:
3 Leave the URL unchanged: If you do not return any value or return an empty string,
the URL is left unchanged.
3 Change the URL: If you wish to change the URL, you may do so by returning a nonempty string. The URL must be non-URL encoded Unicode.
3 Modify the query: If you wish to modify the query, you may directly modify the
contents of the built in _query collection (or _form collection if parameter mode is set to form variables in Active4D.ini).
3 Reject the request: You may refuse the request altogether by calling set response
status with a status other than 200 (OK), such as 404 (Not Found) or 303 (See Other). If you set the response status to something other than 200, you do not need to return a result.
3 Redirect: You may redirect to another URL by setting a response of 303 (See Other) or
301 (Moved Permanently) and setting a Location response header with the full target URL (including query), which should be url encoded UTF-8. If you do a redirect in this way, you do not need to return a result.
124
Chapter 10
Event Handlers
Active4D v5
The request info, request cookies, response headers and response cookies collections are accessible within this handler. This allows you to check things like the host, set cookies, etc.
On Authenticate
When Active4D determines that the current request is in a protected realm, if this event handler is defined it is invoked before the On Session Start and On Execute Start event handlers.
Chapter 10
Event Handlers
125
Active4D v5
In this example we are using a table that defines all of the users and passwords for each realm. If we find a match, we check the passwords to make sure the capitalization is exactly the same. If there is no match, we authenticate again. Be sure to pass along an authentication failure message with the authenticate command, either by writing directly to the response buffer, by including another file, or by utilizing the standard HTTP error handling mechanism as described in HTTP Error Handling on page 59. When the authenticate command returns, the HTTP status code is 401. Within this handler you may access all of the Active4D collections.
On Session Start
This handler is executed when a new user (one with no current session) makes a successful HTTP request (one with a result code of 200 OK), before the On Execute Start handler. Note: Whether or not you set any session items in On Session Start, if this event handler is defined a new session will always be created for each new visitor to your site. Therefore you should only define this method if your intention is to track each new visitor through a session. For example, here is an On Session Start handler that initializes three items in a session:
method "On Session Start" session{"start"} := 1 session{"recsPerPage"} := 10 session{"sortAscending"} := true end method
126
Chapter 10
Event Handlers
Active4D v5
The first time a user makes a request from your site, these three session items will be set. For more information on sessions, see Sessions on page 313. If you want to initialize new sessions only when a certain event occurs, such as a successful user login, do not use this handler. Rather, initialize your session at the point at which you determine one is needed. You can use the requested url command to determine which part of your web site was accessed, thus determining how to initialize the session. You may also use the redirect command to force all new sessions to go to a login page, for example. For the redirect trick to work, if you are using session cookies the user must have cookies on, otherwise you will end up in an endless loop. To prevent this, in the redirect page you must check for the presence of the session cookie, and if it is not there you must then redirect to a static HTML page (not an executable page!) which tells the user they must turn cookies on. Within this handler you may access all of the Active4D collections.
On Execute Start
This handler is executed before Active4D begins execution. Typical uses for this handler would include dumping some debugging information, or initializing timing information. Because this handler is executed before the requested file is parsed, any HTML you write to the response buffer will appear before the opening <html> tag. It is possible that some browsers may not like this, although both Internet Explorer and Netscape seem to handle it without problems. Within this handler you may access all of the Active4D collections.
On Execute End
This handler is executed after Active4D completes execution, unless the redirect command was called. Within this handler you may access all of the Active4D collections.
On Session End
This handler is executed when a session goes to heaven (if it has been good), either because it timed out, it was expired with the abandon session command, the Active4D server has been restarted, or because the server is shutting down. Typically you would use this handler to clean up data that was stored during the course of the users session. For example, if the user uploaded a file and you stored the path to the file in the session, when the session times out you would use this handler to delete the file. Because this handler is executed asynchronously at idle time, the only Active4D collection you have access to is the globals collection, as there is no request context. However, the about-to-be-purged session is made current and you can access all of its data one last time before kissing it goodbye.
Chapter 10
Event Handlers
127
Active4D v5
3 If you wish to identify a session persistently, always use session internal id, as the
result of session id is undefined in this handler.
3 There is no deterministic way of knowing when this handler will run. The only thing
you know for sure is that it will run sometime after a session expires.
3 If multiple sessions have expired when a session purge cycle begins, this handler will
be run once for each session. However, there is no deterministic way of knowing the order in which the sessions will be handled.
On Application End
This handler is executed just before the server shuts down, either when 4D is shutdown or when the Active4D server is restarted. This handler is analogous to the On Exit database method in 4D. The only Active4D collection you have access to in this handler is the globals collection.
This technique allows you to make modifications to the event handling code without affecting the Active4D library itself. Because the _active4d library is a normal library, when you modify the code in that library, the library will automatically be reloaded.
128
Chapter 10
Event Handlers
CHAPTER 11 ..............................................................
Command Reference
Active4D implements over 460 commands that provide unparalleled power and simplicity to web site programming. Of these commands, over 170 are 4D commands. The remaining 300 commands are specific to Active4D.
4D Commands
Following is a list of the 4D commands implemented by Active4D. Unless indicated by the formats noted below, they take the same parameters and work exactly as they do in 4D.
3 Commands in bold have been enhanced by Active4D. 3 Commands in italics have a limitation relative to the 4D v11 version.
Any commands which were added or extended in 4D v11+ are implemented in their extended form in Active4D. Note: Unlike 4D, the 4D commands used by Active4D are always in English. If you are using a foreign language version of 4D, please be aware that you will have to use English commands and named constants in Active4D.
Chapter 11
Command Reference
129
130
Chapter 11
Command Reference
Chapter 11
Command Reference
131
Active4D v5
Active4D Commands
Active4D implements almost 300 of its own commands. Most are focused on web programming. Some are additions to the 4D language that we have always wanted. The bottom line is this: if you learn these new commands, you will be far more productive. So please take the time to learn them!
132
Chapter 11
Command Reference
Chapter 11
Command Reference
133
134
Chapter 11
Command Reference
Chapter 11
Command Reference
135
Active4D v5
Command Syntax
The commands in this chapter are listed with the same basic format that the 4D documentation uses, with a few small differences:
3 Parameters have a prefix to indicate what happens to them within the body of the
method. The prefix in means the value of the parameter is read but not written. The prefix io means the value is both read and written. The prefix out means the value is written, replacing any existing value.
136
Chapter 11
Command Reference
Arrays
Active4D v5
Arrays
Active4D adds several commands and an extended syntax which make working with arrays much easier. It will pay many times over for you to learn and use these commands.
Chapter 11
Command Reference
137
Active4D v5
Arrays
{} (appending index)
<array>{}
version 4.0
Discussion Active4D adds a new syntax for appending elements to an array. If you use an empty index with an array, a new element is appended to the array and the index is set to the newly appended element. This allows you to add items to an array in a very simple way, like this:
array longint($longs; 0) $longs{} := 7 // same as append to array($longs; 7) $longs{} := 13 // same as append to array($longs; 13) // $longs now contains 2 elements, 7 and 13
version 4.5
Discussion Active4D adds a new syntax for referencing elements relative to the end of an array. By using a negative index, you index array elements from the end of the array, with -1 being the last element and -Size of array being the first element. For example, to reference the last element of an array, you can simply do this:
$myArray{-1} := 7 // old way, which one is easier? $myArray{size of array($myArray)} := 7
138
Chapter 11
Command Reference
Arrays
Active4D v5
add element
add element(ioArray {; inHowMany}) Parameter ioArray inHowMany Type Array Number
version 1
Description The array to which you want to append elements How many elements to append
Discussion This command appends one or more empty elements to ioArray. If inHowMany is omitted, one element is appended to the end of ioArray. The element appended to the array is initialized to the default value for the arrays type. This command is essentially shorthand for the following standard 4D statement:
insert element($ioArray; size of array($ioArray) + 1; $inHowMany)
append to array
append to array(ioArray; inValue {; inValueN}) Parameter ioArray inValue Type Array <any>
Description The array to which you want to append elements Elements to append
Discussion This command appends one or more values to the existing contents of ioArray. If a value is not assignment compatible with ioArray, an error is generated and execution is aborted. Unlike the 4D version of this command, in Active4D you can append multiple values at once, like this:
append to array($array; "one"; "two"; "three")
Note: If you want to unconditionally set the contents of an array when it is declared, it is easier to use the extended array declaration syntax. If you want to reset the contents of an array after it has been created, as opposed to appending, you might want to use the set array command.
Chapter 11
Command Reference
139
Active4D v5
Arrays
ARRAY <type>
Discussion This command allows you to declare or resize an array and define its elements in one statement. If type is a STRING or TEXT, the values are automatically converted to the appropriate type with the default string conversion. For all other types, if a value is not assignment compatible with type, an error is generated and execution is aborted. Examples
// 4D way array text($items; 3) $items{1} := "one" $items{2} := string(current date) $items{3} := string(?07:27:13?) // easier Active4D way array text($items; 0) set array($items; "one"; string(!04/13/64!); string(?07:27:13?)) // easier way array text($items; *; "one"; !04/13/64!; ?07;27;13?)
Note: As with 4D in Unicode mode, ARRAY STRING actually creates ARRAY TEXT.
clear array
clear array(ioArray {; ioArrayN}) Parameter ioArray Type Array Description Array to clear
version 2
140
Chapter 11
Command Reference
Arrays
Active4D v5
COPY ARRAY
COPY ARRAY(inSourceArray; ioDestArray {; inStart; inEnd}) Parameter inSourceArray ioDestArray inStart inEnd Type Array Array Number Number
Description Array from which to copy Array to receive copied elements Starting element to copy Ending element to copy
Discussion If inStart and inEnd are not passed, this command works exactly like it does in 4D. If inStart and inEnd are passed, ioDestArray will receive a copy of that subrange of elements. If inStart is zero, elements are copied starting at the zero element of ioDestArray, otherwise elements are copied starting at the first element of ioDestArray.
Count in array
Count in array(inArray; inValue {; inStart}) Number Parameter inArray inValue inStart Result Type Array Array Number Number
(modified 4D) v5
Description Array to search Value to search for Element at which to start searching Occurrences of inValue
Discussion This command differs from the 4D version of this command in that you can pass inStart to specify where to start searching for inValue. If inStart is not passed, it defaults to 1. If inStart is less than zero, it is pinned to zero. If it is greater than the size of inArray, the result will be zero.
Chapter 11
Command Reference
141
Active4D v5
Arrays
fill array
fill array(ioArray; inStart {; inEnd {; inStep {; inArrayStart}}}) Parameter ioArray inStart inEnd inStep inArrayStart Type Longint/Real array Number Number Number Number
version 4.0
Description The array to fill Starting number in sequence or size of sequence Ending number in sequence Difference between steps in sequence Where to start filling array
Discussion This command fills an array with a sequence of values. In its simplest form, you can just pass an array and an integral number. In that case the array will be filled with a sequence of values from 1 to inStart inclusive, starting at element 1 of ioArray. If ioArray does not exist when this command is called, it is created as a Real array. If both inStart and inEnd are passed, the sequence will start at inStart and increment by 1 until Abs(step) > Abs(inEnd). If inStep is passed, the sequence will start at inStart and increment by inStep until Abs(step) > Abs(inEnd). All of these parameters may be nonintegral. If inArrayStart is passed, the sequence begins at that element. If inArrayStart > Size of array(ioArray), the array is extended accordingly. Examples
// fill an array with numbers 1-100 fill array($array; 100) // fill an array with numbers 10 to -10 fill array($array; 10; -10; -1) // fill an array with numbers from 1 to 2.5 by .5 fill array($array; 1; 1; 2.5; .5)
142
Chapter 11
Command Reference
Arrays
Active4D v5
version 4.0
Description Array into which to insert Element before which values are inserted Values to insert
Discussion This command inserts one or more values into the existing contents of ioArray. The first inserted value will be element inWhere. If inWhere > Size of array(ioArray), the values are appended. If a value is not assignment compatible with ioArray, an error is generated and execution is aborted.
is array
is array(inType) Boolean Parameter inType Result Type Longint Boolean
version 2
Discussion This command returns true if the given variable type is an array type. It is shorthand for the following test:
// 4D way $isArray := ((Type($var) >= Array 2D) & \\ (Type($var) <= Boolean array)) // Active4D way $isArray := is array(type($var))
Chapter 11
Command Reference
143
Active4D v5
Arrays
join array
version 2
join array(inArray; inSeparator {; inStart {; inPrefixNum {; inQuoteText}}}) Text Parameter inArray inSeparator inStart inPrefixNum inQuoteText Result Type Array Text Number Boolean Boolean Text Description The array to join The text to insert between elements The element to begin joining from True to prefix the element number True to quote-enclose elements of Text or String arrays Concatenation of array elements
Discussion This command joins the elements of inArray together into a single string. Non-textual array elements are automatically converted to text. If inStart is not specified, it defaults to 1. If inPrefixNum is not specified, it defaults to False. If it is specified and True, each element is prefix by {#} where # is the element number. , If inQuoteText is not specified, it defaults to False. If it is specified and True, elements of text or string arrays are surrounded by double quotes. Here are some examples:
array longint($longs;0) set array($longs; 7; 13; 27) writebr(join array($longs; ", ")) array text($nums;0) set array($nums; "one"; "two"; "three") writebr(join array($nums; "<br />"; 1; true; true)) // Here is the output in the browser 7, 13, 27 {1} "one" {2} "two" {3} "three"
This command is especially useful for writing the contents of an array to the Active4D debugging console. Use this form:
write to console(join array($array; "\r"; 1; true; true))
144
Chapter 11
Command Reference
Arrays
Active4D v5
multisort arrays
multisort arrays(inArray1; inDirection1 {; inArrayN; inDirectionN}) Parameter inArray inDirection Type Array <>= or Text Description The array to sort The sort direction
version 3.0
Discussion This command performs a multilevel sort on the elements of inArray1 through inArrayN. The direction of the sort for each array is specified by the the inDirection argument following the array: Character > < = Direction Ascending Descending Dont care, follow array to left
You may sort any array type except for picture arrays and pointer arrays. The arrays may be local, process, or interprocess variables. The sort direction may be one of the operators >, < and =, or may be any text expression which resolves to one of those characters. This allows you to programmatically set the direction of the sort.
version 3.0
multisort named arrays(inArrayName1; inDirection1 {; inArrayNameN; inDirectionN}) Parameter inArrayName inDirection Type Text <>= or Text Description The name of an array to sort The sort direction
Discussion This command is identical to multisort arrays, except that instead of passing direct array references, you pass text expressions which resolve to the names of arrays. This allows you to programmatically determine both the order and direction of the sort. The arrays names should begin with $ to indicate a local array, <> to indicate an interprocess array, and no prefix to indicate a process array.
Chapter 11
Command Reference
145
Active4D v5
Arrays
resize array
resize array(ioArray; inSize) Parameter ioArray inSize Type Array Number
version 3.0
Description The name of an array to sort The new size of the array
Discussion This command resizes ioArray to the given size. If inSize is less than zero, the array will be resized to zero.
Discussion These commands have been enhanced in that the array arguments may be any valid array reference, including collection items which do not yet exist. This allows you to load data directly into collections (including built in collections like session), like this:
selection to array([ingredients]id; session{"ids"}; \\ [ingredients]name; session{"names"}; \\ [vendors]name; session{"vendors"})
set array
set array(ioArray; inValue {; inValueN}) Parameter ioArray inValue Type Array <any>
version 2
Description The array which you want to set to the given elements Elements to set
Discussion This command replaces the existing contents of ioArray with one or more values. If a value is not assignment compatible with ioArray, an error is generated and execution is aborted.
146
Chapter 11
Command Reference
Arrays
Active4D v5
This command is the fastest way to initialize an array to a known set of values. For example:
array longint($primes;0) set array($primes; 2; 3; 5; 7; 11; 13)
Chapter 11
Command Reference
147
Active4D v5
BLOBS
BLOBS
The BLOB commands supported by Active4D function exactly as they do in 4D. Active4D adds two named constants for use with the LONGINT TO BLOB and BLOB to longint commands:
3 Intel byte ordering: This is the equivalent of the 4D named constant PC byte ordering. 3 PPC byte ordering: This is the equivalent of the 4D named constant Macintosh byte
ordering. You should prefer the Active4D equivalents over the 4D constants because they avoid the confusion arising from the fact that all new Macintoshes have used so-called PC byte ordering for several years, ever since the move to Intel processors.
148
Chapter 11
Command Reference
Collections
Active4D v5
Collections
The collection commands allow you to create, manipulate, examine and destroy your own local (temporary) or global (persistent) collections within your scripts. For more information on collections, see Collections on page 95. Note: Many of the collection commands are no longer necessary as they have been replaced with the extended indexing syntax, which is much easier to use. They have been retained for backwards compatibility. For more information, see Referencing Collection Values on page 96.
Chapter 11
Command Reference
149
Active4D v5
Collections
collection
collection(inHandle) Longint Parameter inHandle Result Type Longint Longint Description Collection handle Iterator reference
version 2
Discussion Given a collection, this command returns an iterator to the first item in the collection. For more information on iterators, see Iterators on page 208.
new collection
Discussion This command creates a new local or global collection and returns a handle to the collection. You then use this handle with the other collection commands. If no * is passed, this command is exactly equivalent to new local collection. If * is passed, this command is exactly equivalent to new global collection. You may also initialize the collection with key/value pairs by passing pairs of parameters. If an array is passed as the value, it is stored in its entirety in the item. For example, this code would create a local collection and initialize it with two items:
$person := new collection("name"; [People]Name; \\ "age"; [People]Age)
150
Chapter 11
Command Reference
Collections
Active4D v5
version 2
Discussion This command creates a new local collection and returns a handle to the collection. You then use this handle with the other collection commands. This command is exactly equivalent to new collection. A collection created with this command is automatically cleared by Active4D when the script finishes execution. Warning: You should always assign a local collection handle to a local variable or local collection item in the same scope.
new global collection{(inKey; inValue {; inKeyN; inValueN})} Longint Parameter inKey inValue Result Type Text <any> Longint Description Item key Item value Collection handle
Discussion This command creates a new global collection and returns a handle to the collection. You then use this handle with the other collection commands. This command is exactly equivalent to new collection(*). A collection created with this command remains in memory until the server shuts down or until it is deleted with clear collection or deep clear collection. Warning: Be sure to store the handle in a place where you can retrieve it later, such as in the globals collection.
Chapter 11
Command Reference
151
Active4D v5
Collections
collection to blob
collection to blob(inRef {; ioBlob}) BLOB | <none> Parameter inRef ioBlob Result Type Longint BLOB BLOB
Description Collection handle or iterator BLOB to append data to Serialized collection data
Discussion This command serializes the data in the collection referenced by inRef. If ioBlob is passed, the serialized data is appended to ioBlob and nothing is returned. If ioBlob is not passed, the serialized data is returned as a new BLOB. In either case, you can store the BLOB somewhere for later restoral via blob to collection. To recursively serialize a collection, use the library method a4d.utils.collectionToBlob. Warning: Do not attempt to serialize a v5 collection and then load it with a previous version of Active4D.
blob to collection
blob to collection(inBLOB {; ioOffset }{; *}) Longint Parameter inBLOB ioOffset * Result Type BLOB Number * Longint
Description BLOB with serialized collection data Offset within BLOB to get data Create a global collection Collection handle
Discussion This command creates a new collection from the serialized collection data contained in inBLOB. If ioOffset is passed, the serialized data must begin at that byte offset within inBLOB. After the collection is successfully deserialized, ioOffset will point to the first byte beyond the serialized data. If inBLOB was not created with collection to blob, an error will be generated and execution will be aborted.
152
Chapter 11
Command Reference
Collections
Active4D v5
If the optional * parameter is given, the new collection is a global collection, otherwise the collection is local and will be cleared when the current script is finished executing.. Note: Active4D v5 will deserialize collections serialized with Active4D 4.x.
save collection
save collection(inRef; inPath) Parameter inRef inPath Type Longint Text
version 4.0
Discussion This command directly saves a serialized collection. It is effectively the same as:
$blob := collection to blob($inRef) blob to document($inPath; $blob)
Warning: Do not attempt to serialize and save a v5 collection and then load it with a previous version of Active4D.
load collection
load collection(inPath) Longint Parameter inPath Result Type Text Longint Description File path Collection handle
version 4.0
Discussion This command directly loads a serialized collection. It is effectively the same as:
document to blob($inPath; $blob) $collection := blob to collection($blob)
Chapter 11
Command Reference
153
Active4D v5
Collections
copy collection
copy collection(inRef {; *}) Longint Parameter inRef * Result Type Longint * Longint
Discussion This command makes a shallow copy of the collection referenced by inRef and returns a handle to the copy. You can then use this handle with the other collection commands. If the optional * parameter is given, the new collection is a global collection, otherwise the collection is local and will be cleared when the current script is finished executing. Because this command makes a shallow copy of inRef, collection references embedded within inRef will not be copied, and the original will still be referred to in the copy. To make a deep (recursive) copy, use the deep copy collection command.
version 4.0
Discussion This command makes a deep (recursive) copy of the collection referenced by inRef and returns a handle to the copy. You can then use this handle with the other collection commands. If the optional * parameter is given, the new collection is a global collection, otherwise the collection is local and will be cleared when the current script is finished executing. When copying inRef, the following recursive algorithm is followed: 1 2 3 A shallow copy of the inRef is made. The type of each item in the copy is checked. If the item is a Longint and is a collection handle, the value is replaced with the result of a deep copy of that collection.
154
Chapter 11
Command Reference
Collections
Active4D v5
If the item is a Longint Array, each element of the array is checked to see if it is a collection, and if so the element is replaced with the result of a deep copy of that collection. Warning: Circular collection references encountered by this command will cause Active4D (and 4D) to die a horrible death.
merge collections
merge collections(inRef1; inRef2 {inRefN} {; *}) Longint Parameter inRef * Result Type Longint * Longint
version 3.0
Discussion This command merges all of the collections referenced by inRef1inRefN and returns a handle to the merged collection. You can then use this handle with the other collection commands. The merged collection is the union of all of the items in referenced collections. Because the collections are merged from left to right, if items two or more collections have the same key, the items in the collections to the right will overwrite those to the left. If the optional * parameter is given, the new collection is a global collection, otherwise the collection is local and will be cleared when the current script is finished executing. Example
// We want a merge of form variables and query params c_longint($attributes) $attributes := merge collections(form variables; query params)
Chapter 11
Command Reference
155
Active4D v5
Collections
clear collection
clear collection(inHandle) Parameter inHandle Type Longint Description Collection handle
version 2
Discussion This command deletes the collection and all of its items. After using this command, inHandle is no longer a valid collection handle. Note: You may use this command on local collections, but there is usually not much point as local collections are automatically cleared when script execution ends.
version 4.0
Discussion This command deletes the collection and all of its items. After using this command, inHandle is no longer a valid collection handle. Note: You may use this command on local collections, but there is usually not much point as local collections are automatically cleared when script execution ends. When clearing inHandle, the following recursive algorithm is followed: 1 2 3 The type of each item is checked. If the item is a Longint and is a collection handle, a deep clear of that collection is performed. If the item is a Longint Array, each element of the array is checked to see if it is a collection, and if so a deep clear of that collection is performed. Warning: Circular collection references encountered by this command will cause Active4D to die horribly.
156
Chapter 11
Command Reference
Collections
Active4D v5
get collection
get collection(inRef; inKey {; inIndex}) <any> Parameter inRef inKey inIndex Result Type Longint Text Longint <any>
Description Collection handle or iterator Key of collection item to retrieve Index of array element to retrieve Value of collection item or ""
Discussion This command searches the collection specified by inRef for the item with the key inKey. If the item is found and inIndex is not specified, the items value is returned. If the item value is an array, an empty string is returned. If the item is found and an index is specified, the given array element is returned. If the index is out of range, an error is generated and execution is aborted. If the item is not found, an empty string is returned. Note: This command has been superceded by the simpler syntax: collectionRef{inKey} or collectionRef{inKey}{inIndex}
Description Collection handle or iterator Key of collection item to retrieve Receives the array
Discussion This command searches the collection specified by inRef for the item with the key inKey. If outArray is not an array, an error is generated and execution is aborted. If the item is found and its value is an array, outArray receives a copy. If outArray has not yet been defined, it is created with the same type as the source array. If the item is found and its value is not an array, an error is generated and execution is aborted.
Chapter 11
Command Reference
157
Active4D v5
Collections
If the item is not found, outArray is resized to zero. If outArray has not yet been defined, it is created as a text array. Note: This command has been superceded by the simpler syntax: collectionRef{inKey} If the resulting value is an array, it may be used with all of the array commands such as append to array and DELETE ELEMENT.
Description Collection handle or iterator Key of collection item to check Size of array
Discussion This command searches the collection specified by inRef for the item with the key inKey. If the item is found and its value is an array, the size of the array is returned. If the item is found and its value is not an array, an error is generated and execution is aborted. If the item is not found, zero is returned. Note: This command has been superceded by the simpler syntax: Size of array(collectionRef{inKey})
Description Collection handle or iterator Key of collection item to retrieve Iterator for collection
158
Chapter 11
Command Reference
Collections
Active4D v5
Discussion This command searches the collection specified by inRef for the item with the key inKey. If the item is found, an iterator reference for the item is returned. If the item is not found, an empty iterator is returned. For information on empty iterators, see Iterating Over a Collection on page 98.
version 4.0
Description Collection handle or iterator Key of form variable to check Size of array
Discussion This command searches the form variables collection for the item with the key inKey. If the item is found and contains an array, the size of the array is returned. If the item is found and its value is not an array, 1 is returned. If the item is not found, zero is returned.
Discussion This command fills outKeys with all of the keys in the collection. If outKeys has not yet been defined, it is created as a string array. If outKeys is defined but is not a string or text array, an error is generated an execution is aborted.
Chapter 11
Command Reference
159
Active4D v5
Collections
set collection
set collection(inHandle; inKey; inValue {; inKeyN; inValueN | inIndex}) Parameter inHandle inKey inValue inIndex Type Longint Text <any> Longint
version 2
Description Collection handle Key of collection item to store Value to set for the given item Index of array element to set
Discussion This command searches the collection specified by inHandle for the item with the key inKey. If the item is found and its value is not an array, you may pass more than one key/value pair to set multiple items at once. If the item is found and its value is an array, you may pass an index to set an element of the array. If the item is found and an index is not specified, the items value is replaced with inValue. If the item is found, its value is an array, and an index is specified, the given array element is set. If the index is out of range or the type of inValue is not assignment-compatible with the array, an error is generated and execution is aborted. If the item is not found and an index is not specified, a new item is added to the collection with the given keys and values. If the item is not found and an index is specified, an error is generated and execution is aborted. Here is an example of set collection using multiple items:
$c := new collection set collection($c; "name"; "Aparajita"; "age"; 40) // Collection now contains two items
Note: This command has been superceded by the simpler syntax: collectionRef{inKey} := inValue or collectionRef{inKey}{inIndex} := inValue
160
Chapter 11
Command Reference
Collections
Active4D v5
version 2
Description Collection handle Key of collection item to store Array to set for the given item
Discussion This command searches the collection specified by inHandle for the item with the key inKey. If inArray is not an array, an error is generated and execution is aborted. If the item is found, its value is replaced with inArray. If the item is not found, a new item is added to the collection with the given key and array. Note: This command has been superceded by the simpler syntax: collectionRef{inKey} := inArray
is a collection
is a collection(inRef ) Boolean Parameter inRef Result Type Longint Longint
Discussion This command tests a Longint to ensure it is a collection handle. Although Active4D tests the validity of collection handles in commands that take one, if the handle is not valid an error is generated and execution is aborted. If you are unsure if a Longint is a collection handle and you dont want your script to be prematurely aborted, you should use this command to test the Longint before passing it to a collection command.
Chapter 11
Command Reference
161
Active4D v5
Collections
collection has
collection has(inRef; inKey {; *}) Boolean Parameter inRef inKey * Result Type Longint Text * Boolean
Description Collection handle or iterator Key of collection item to test Perform wildcard search True if key is in collection
Discussion This command searches the collection specified by inRef for the item with the key inKey. If * is passed, inKey may contain 4D wildcard characters and they will be honored in the search. If the item is found, True is returned, otherwise False. If a collection value might be a non-text type, it is not sufficient to get its value and check for an empty string being returned. In such cases you should always use this command to test for the existence of a collection item, as shown here:
$c := new local collection if ($c{"test"} # "") // This would break if "test" existed and was a number end if // The correct way if (collection has($c; "test")) $test := $c{"test"} else $test := "this is a test" $c{"test"} := $test end if
162
Chapter 11
Command Reference
Collections
Active4D v5
Discussion This command returns the number of items in the collection specified by inRef.
version 2
Discussion This command searches the collection specified by inHandle for the item with the key inKey. To delete more than one item, you may use a wildcard in the key. All items that match will be removed from the collection.
Chapter 11
Command Reference
163
Active4D v5
Cryptography
Cryptography
Active4D provides a few simple commands for doing basic encryption/decryption and hashing of text, in case you need to make aspects of your site more secure. Each of the cryptography commands has a corresponding plugin command accessible from 4D, so that you can share encrypted data between 4D and Active4D. The details of the various cryptographic algorithms employed are beyond the scope of this document. There is a wealth of information on cryptography online.
164
Chapter 11
Command Reference
Cryptography
Active4D v5
base64 decode
base64 decode(inText {; inCharset {; * | inURLSafe}}) Text | BLOB base64 decode(inBlobData) BLOB Parameter inText inCharset * inURLSafe Result inBlobData Result Type Text Text * Boolean Text | BLOB BLOB BLOB
Description Base64 encoded text Charset of decoded text Use URL safe mode True to use URL safe mode Original data Base64 encoded data Original data
Discussion This command decodes text that was encoded with base 64 encoding (such as the base64 encode command). If passed text and no charset, base64 decode returns a BLOB. If passed text and a charset, base64 decode decodes the text, converts from the given charset to Unicode, and returns Unicode text. If * is passed or inURLSafe is passed and is True, text is assumed to be in a URL safe form of base 64 encoding where + and / are replaced with - and _ and the = padding at the end is stripped. If you do URL safe decoding, be sure the text was encoded in a URL safe form. When text is passed, whitespace (carriage return, linefeed, space, tab) in the text is ignored. If the text contains invalid base64 characters, an empty string is returned. If passed a BLOB, base64 decode returns a BLOB, because there is no guarantee that the decoded data contains valid Unicode.
Chapter 11
Command Reference
165
Active4D v5
Cryptography
base64 encode
base64 encode(inText {; inCharset {; * | inURLSafe}}) Text base64 encode(inBlobData) Text Parameter inText inCharset * inURLSafe Result inBlobData Result Type Text Text * Boolean Text BLOB Text
Description Original text Charset of encoded text Use URL safe mode True to use URL safe mode Encoded text Original data Encoded data
Discussion This command encodes arbitrary bytes of binary data as a base 64 number which is represented by a letter or symbol in the 7-bit ASCII character set. The 7-bit ASCII nature of this text makes it easy to use in a URL, store in a database text field, etc., because it will never be changed due to character set conversions. This command is primarily designed to be used in conjunction with blowfish encrypt, which returns 8-bit ASCII. Because Unicode is a multibyte character set and base 64 is byte-oriented, Unicode text must be converted to a byte-oriented character set before it is encoded. By default, Unicode text passed to base64 encode is converted to Mac Roman for backwards compatibility. You can specify another character set (such as UTF-8) by passing the inCharset parameter, which should be a valid IANA charset name. If the name is empty, it defaults to Mac Roman. If the name is not valid, an error is generated and execution is aborted. Note: The charset you choose should be byte-oriented (e.g. UTF-8), not multibyte (e.g. UTF-16). If * is passed or inURLSafe is passed and is True, a URL safe form of base 64 encoding is created where + and / are replaced with - and _ and the = padding at the end is stripped. If you create URL safe encoding, be sure to do URL safe decoding as well. base64 encode can take a BLOB as the first parameter, in which case the bytes of the blob are encoded directly and no charset is necessary.
166
Chapter 11
Command Reference
Cryptography
Active4D v5
Example
$id := string(session{"user.id"}) $enc := blowfish encrypt($id; "test"; "test"; "utf-8") $qry := build query string(""; "u"; base64 encode($enc))
blowfish decrypt
blowfish decrypt(inBlob; inPassphrase {; inIV {; inCharset {; *}}}) Text | <none> Parameter inBlob inPassphrase inIV inCharset * Result Type BLOB Text Text Text * Text | <none> Description Encrypted data to decrypt Key used to encrypt data IV used to encrypt data Charset of encrypted text Decrypt in place Encrypted text
Discussion This command decrypts data that was encrypted with the Blowfish symmetric block cipher (such as the blowfish encrypt command). The passphrase and initialization vector (inIV) must be the same as those that were used to encrypt the text. If * is not passed, the decrypted BLOB is converted to Unicode text. If inCharset is not passed in, the decrypted data is converted from Mac Roman for backwards compatibility. You can specify another character set (such as UTF-8) by passing inCharset, which should be a valid IANA charset name. If the name is empty, it defaults to Mac Roman. If the name is not valid, an error is generated and execution is aborted. Note: The charset you choose should be byte-oriented (e.g. UTF-8), not multibyte (e.g. UTF-16). If * is passed, the data is decrypted in place and nothing is returned.
Chapter 11
Command Reference
167
Active4D v5
Cryptography
blowfish encrypt
blowfish encrypt(inText; inPassphrase {; inIV {; inCharset}}) BLOB blowfish encrypt(inBLOB; inPassphrase {; inIV {; inCharset {; *}}}) BLOB | <none> Parameter inText inPassphrase inIV inCharset Result inBLOB inPassphrase inIV inCharset * Result Type Text Text Text Text BLOB BLOB Text Text Text * BLOB Description Text to encrypt Key to encrypt/decrypt text Seed text for encryption Character set to convert to Encrypted data Data to encrypt Key to encrypt/decrypt data Seed text for encryption Character set to convert to Encrypt in place Encrypted data
Discussion This command encrypts inText or inBLOB with the Blowfish symmetric block cipher. Blowfish encryption and decryption in Active4D use a variable length key between 1 and 56 bytes and an eight-byte IV, or initialization vector. After conversion to the target character set, both the key and IV are truncated to the maximum length or padded with spaces to the minimum length. Text to be encrypted is converted from Unicode to the target character set, then padded with PKCS#5 padding to an even multiple of eight bytes before encryption. If you are encrypting and decrypting within Active4D, you dont need to know this, but if you are sharing encrypted data with other software, you need to know the encryption format. inPassphrase is the key with which you encrypt and decrypt the text. It must be nonempty. In addition, you may supply an initialization vector, or seed text, in the inIV parameter. The initialization vector (IV) is used as the seed text which the encryption algorithm uses. You may leave it empty if you wish. By default, the text, passphrase and IV are converted to Mac Roman for backwards compatibility. You can specify another character set (such as UTF-8) by passing the inCharset parameter, which should be a valid IANA charset name. If the name is empty, it defaults to Mac Roman. If the name is not valid, an error is generated and execution is aborted. Note: The charset you choose should be byte-oriented (e.g. UTF-8), not multibyte (e.g. UTF-16).
168
Chapter 11
Command Reference
Cryptography
Active4D v5
Typically the IV is used to add a bit of randomness to the encrypted text, to make it harder for potential crackers to determine the passphrase. Because the IV must be known in order to decrypt, it is usually added to the encrypted text and then retrieved when the text is decrypted. For example, you could do something like this:
// encryption $enc := blowfish encrypt(string(milliseconds); "ivpass"; "") $iv := substring(base64 encode($enc); 1; 8) $enc := blowfish encrypt("Some text"; "secret pass"; $iv; "utf-8") $encText := $iv + base64 encode($enc) $queryValue := url encode query($encText) // decryption $encText := _query{"q"} // already url decoded by Active4D $iv := substring($encText; 1; 8) // separate IV $encText := susbstring($encText; 9) $encText := base64 decode($encText; "utf-8") $text := blowfish decrypt($encText; "secret pass"; $iv)
Like I said, you could do something like the above if you are paranoid or are operating in an environment where your data is so valuable that it is worth it for someone who has both significant knowledge of cryptographic algorithms and significant computing resources to attempt to crack your encryption. In other words, for the vast majority of us, it is quite sufficient to use either no IV or the same IV all of the time. If you pass a BLOB as the first parameter and do not pass *, an encrypted BLOB is returned. If you pass a BLOB and *, the BLOB is encrypted in place and nothing is returned. Note: blowfish encrypt always encrypts to a BLOB in Active4D v5 because encryption actually creates a bunch of numbers which cannot reliably be converted to valid Unicode text.
Chapter 11
Command Reference
169
Active4D v5
Cryptography
md5 sum
md5 sum(inData {; inCharset}) Text md5 sum(inData) Text Parameter inText inCharset Result inData Result Type Text Text Text BLOB Text Description Original data Charset to convert to MD5 hash Original data MD5 hash
Discussion This command performs an MD5 hash of inData, which results in a 128-bit (16-byte) checksum that is returned as a 32-byte hexidecimal number. MD5 is a one-way algorithm designed to uniquely identify a sequence of bits in a secure manner. You cannot reconstruct the original data from the resulting MD5 checksum. If inData is text and inCharset is not passed, the text is converted to Mac Roman for compatibility with Active4D v4.x. If inCharset is passed and is empty, it defaults to Mac Roman. Otherwise it should be a valid IANA character set name or alias. If the name is invalid, an error is generated and execution is aborted. For a complete list of valid character set names, see: http://demo.icu-project.org/icu-bin/convexp?s=IANA&s=ALL You may also pass a BLOB to this command to calculate a hash on arbitrary data.
170
Chapter 11
Command Reference
Database
Active4D v5
Database
Active4D adds a few database commands which make it easier to dynamically get pointers to tables and fields.
Trigger Errors
If your database uses triggers which return your own error numbers (-15000 to -32000), those errors are available from Active4D for the following triggers:
Chapter 11
Command Reference
171
Active4D v5
Database
Field name
Field name(inFieldPtr {; *} | inTableNum; inFieldNum {; *}) Text Parameter inFieldPtr inTableNum inFieldNum * Result Type Pointer Number Number * Text
Description Field pointer Number of fields table Fields number Return full [table]field ref Field name
Discussion Active4D enhances the 4D version of the Field name command with an extra option. If * is passed as the last parameter, the full [table]field reference will be returned.
version 1
Description Table or field reference as text Receives the table number Receives the field number
Discussion This command resolves a table or field reference in the form [table] or [table]field into the corresponding table and field numbers. It allows you to dynamically build a table or field reference as a string and then resolve it. If inReference is not a valid table or field reference, both outTableNum and outFieldNum will be zero. If the reference is valid but only a table is passed, outFieldNum will be zero.
172
Chapter 11
Command Reference
Database
Active4D v5
version 1
Description Table number of pointer Field name (no table) Table or field reference as text Pointer to table or field
Discussion The first form of this command takes two parameters. The first parameter is a table number or pointer, and the second is a field name (without a table name). If inField is a valid field name within the table referenced by inTable, a pointer to the field is returned, otherwise a nil pointer is returned. The second form of this command takes one parameter, which is a table or field reference in the form [table] or [table]field If inReference is a valid table or field . reference, a pointer to that table or field is returned. If inReference is not valid, a nil pointer is returned.
QUERY
QUERY(inTable; {; inConjunction}; inField; inComparator; inValue {; *}) Parameter inTable inConjunction inField inComparator inValue Type [table] Logical | Text [table]field Operator | Text <any>
version 1 modified v2
Description Main table on which to query Conjunction with previous line Field on which to query How to compare field with value Value to compare against field
Discussion 4D supports a query syntax that is, as far as I can tell, completely undocumented but seems to be known by many. The undocumented syntax differs from the documented syntax in that:
3 inConjunction may be used on the first line of a built query 3 inConjunction may be a string (& | or #) , 3 inComparator and inValue may be separate arguments 3 inComparator may be a string (= # <, <= > or >=) , , , ,
Chapter 11
Command Reference
173
Active4D v5
Database
Active4D supports this syntax fully, which is especially useful as it allows you to more easily build a dynamic query.
QUERY BY FORMULA
QUERY BY FORMULA({*; } inTable; <expression>) Parameter * inTable expression Type * [table] Boolean
version 1 modified v5
Description Execute within 4Ds context Main table on which to query Boolean expression
Discussion If * is not passed, this command differs from the 4D version of QUERY BY FORMULA in that expression is evaluated by Active4D and must be valid Active4D code. This allows you to call Active4D methods and use local variables in the expression, as well as reference collections like _form, _query, etc. If * is passed, this command is executed on the server within 4Ds context, which means it may execute faster, but you will have no access to Active4Ds variables, collections and methods.
QUERY SELECTION
version 1 modified v2
QUERY SELECTION(inTable; {; inConjunction}; inField; inComparator; inValue {; *}) Parameter inTable inConjunction inField inComparator inValue Type [table] Logical | Text [table]field Operator | Text <any> Description Main table on which to query Conjunction with previous line Field on which to query How to compare field with value Value to compare against field
174
Chapter 11
Command Reference
Database
Active4D v5
Description Execute within 4Ds context Main table on which to query Boolean expression
version 1
Discussion This command differs from the 4D version if inDestination is Into variable:
3 Local variables are not allowed. 3 The process or interprocess variable specified must already be defined, but you can
define them yourself with a compiler declaration within Active4D.
Table name
Table name(inTableNum {; *} | inTablePtr {; *}) Text Parameter inTableNum inTablePtr * Result Type Number Pointer * Text Description Table number Pointer to table Return [tablename] Field name
Discussion Active4D enhances the 4D version of the Table name command with an extra option. If * is passed as the last parameter, the table name will be returned enclosed by square brackets ([ ]).
Chapter 11
Command Reference
175
Active4D v5
Database
176
Chapter 11
Command Reference
Active4D v5
Chapter 11
Command Reference
177
Active4D v5
Date
Date(inYear; inMonth; inDay) Date Parameter inYear inMonth inDay Result Type Number Number Number Date Description Year of date Month of date Day of date Full date
v5 (modified 4D)
Discussion The 4D Date command has been extended to allow you to construct a date from a year, month and day. This allows you to quickly create a date without having to play tricks like constructing a string and then parsing it, or using the idiom:
// old way, obscures your intention $date := add to date(!00/00/00!; $year; $month; $day) // new way, much clearer $date := date($year; $month; $day)
day of year
day of year(inDate) Number Parameter inDate Result Type Date Number
version 2
Discussion This command returns the serial day number within the year represented by inDate. For example:
$day := day of year(!01/01/01!) $day := day of year(!12/31/01!) // $day = 1 // $day = 365
178
Chapter 11
Command Reference
Active4D v5
version 2 modified v5
Description Hour difference between local/UTC time Minute difference between local/UTC time Minute difference between local/UTC time
Result
Number
Discussion In the first form of this command, it returns the number of hours and minutes that would have to be subtracted from the local time to get a UTC time. Note that local times west of Greenwich Mean Time will result in negative outHours. Subtracting this negative number results in adding that many hours to the local time. In the second formof this command, you pass no parameters and it returns the number of minutes that would have to be subtracted from the local time to get a UTC time. In other words, it is the equivalent of:
get utc delta($hours; $minutes) $minutes += $hours * 60
version 2
Discussion This command converts ioDate and ioTime from a date and time in the local time zone to UTC.
Chapter 11
Command Reference
179
Active4D v5
version 2
Discussion This command converts inTime from a time in the local time zone to UTC. The UTC time is normalized to fall in the range 00:00:00 to 23:59:59. The UTC date may be before or after the local date. If you need the date as well, use the local datetime to utc command.
version 2
Discussion This command converts ioDate and ioTime from a date and time in UTC to the local time zone.
version 2
Discussion This command converts inTime from a time in UTC to a time in the local time zone. The local time is normalized to fall in the range 00:00:00 to 23:59:59. The local date may be before or after the UTC date. If you need the date as well, use the utc to local datetime command.
180
Chapter 11
Command Reference
Active4D v5
week of year
week of year(inDate) Number Parameter inDate Result Type Date Number
version 2
Discussion This command returns the serial week number within the year represented by inDate. For example:
$week := week of year(!01/01/01!) $week := week of year(!12/31/01!) // $week = 1 // $week = 53
Note: The week number for dates in the first week of the year may actually be 53. For more information, see the WEEK_OF_YEAR note at: http://userguide.icu-project.org/datetime/calendar#TOC-Disambiguation
Chapter 11
Command Reference
181
Active4D v5
Debugging
Debugging
No development environment would be complete without debugging tools. Although Active4D does not yet have an interactive debugger, it provides a number of debugging tools that allow you quickly and easily view what is going on inside your scripts. Most of the debugging tools are actually part of the standard libraries and 4D shell code distributed with Active4D. The commands in this section are for the most part low level commands used by the debugging tools. For more information on Active4Ds debugging tools, see Chapter 13, Debugging.
182
Chapter 11
Command Reference
Debugging
Active4D v5
version 4.0
Discussion This command returns the name of the library in which execution is taking place at the time this command is called. If this command is executed outside of a library method, an empty string is returned.
version 2
Discussion This command returns the line number of the currently executing method. If the command is not executed within a method, the line number is the line number of the source file in which the command appears. If the command is executed within a method, the line number returned is the line number within the body of the method, not including the method declaration.
version 2
Discussion This command has two forms. If the * is not passed, the name of the current method is returned. If you are currently executing outside of an Active4D method, an empty string is returned. If the * is passed in, a full descriptor of the current execution context is returned as follows:
Chapter 11
Command Reference
183
Active4D v5
Debugging
Descriptor Full URL-style path to the file Method "<method>" Method "<lib.method>"<argument list>
version 3
Discussion This command returns the names of all of the methods in the call chain from the point at which it is executed. outChain must be a local variable, but it need not be defined before calling this command. The chain is represented with the currently executing method in element 1, followed by the caller in element 2, and so on. The names are in the form library.method, except for the top level execution scope, which is called main For inline methods (not declared in . a library), the library name will be global . The values in the outChain array are suitable for passing to the local variables command.
library list
library list(outList) Parameter outList Type Text Array
version 4.0
Discussion This command returns the names of all of the libraries that have been imported. If outList does not exist or is not a Text array, it will created as or converted into a Text array.
184
Chapter 11
Command Reference
Debugging
Active4D v5
write to console
write to console(inValue {; inFormat}) Parameter inValue inFormat Type <any> Text | Number
version 2
Description Value to write to the response buffer Format to use when converting to text
Discussion This command is functionally equivalent to the write command, but instead of appending its output to the response buffer, it appends its output to the Active4D debugging console. For more information on the Active4D debugging console, see Using the Debugging Console on page 558.
Chapter 11
Command Reference
185
Active4D v5
Error Handling
Error Handling
Bad things happen to good people. When things do go wrong, Active4D is there to help you find out why. The commands in this section control the various aspects of error handling in Active4D, which is discussed in Chapter 14, Error Handling. It is recommended that you read that chapter before reading the command descriptions in this section.
186
Chapter 11
Command Reference
Error Handling
Active4D v5
version 1
Discussion This command returns the root-relative error page path for the currently executing script. The default error page is specified by the error page option in Active4D.ini.
version 1
Discussion This command returns the current log level, which determines which errors or messages are logged.
in error
in error Boolean Parameter Result Type Boolean
version 1
Discussion This command returns True if an error page is currently being executed, False if not.
Chapter 11
Command Reference
187
Active4D v5
Error Handling
log message
log message(inMessage {; inIsError}) Parameter inMessage inIsError Type Text Boolean
version 1
Description Message to append to the log file True to mark as an error message
Discussion This command sends inMessage to the Active4D log file if the A4D Log User Messages flag is set in the current log level. Whereas log messages generated by Active4D are marked with Active4D: after the date and time, log messages generated by this command are marked by DB: This allows you to easily filter the log entries by their source. . Because this command has no effect if the A4D Log User Messages flag is not set, you can set the flag during development and use this command to write debugging messages, then turn off the flag during production to eliminate the debug messages. If inIsError is passed and is True, the message will be flagged in the log as an error.
version 1
Discussion After executing this command, any Active4D errors that occur will cause the given script to be executed. To use the default error page as specified by the error page option in Active4D.ini, pass an empty string. The path given should be a URL-style root-relative path. A leading / is ignored. In addition, the path must contain no native directory separators and no directory movement (/../). The path is not validated when this command is executed, but rather when Active4D attempts to load the given error page. Thus it is up to you to ensure that inPath is valid.
188
Chapter 11
Command Reference
Error Handling
Active4D v5
version 1
Discussion This command sets the current log level, which determines which errors or messages are logged.
Chapter 11
Command Reference
189
Active4D v5
File Uploads
File Uploads
The HTTP specification allows for binary objects to be included as part of a posted form, and the HTML specification implements this by providing an input field of type file . When such a field is placed on a form, the browser shows a Browse button, enabling the user to select a file for uploading. When the form is posted, the forms fields and the files contents are specially encoded and sent to the server. Active4D transparently handles the decoding of this type of request for you.
Every file upload command takes a reference as the first parameter. Given an upload reference, you can find out information about the file, copy it from the upload directory to another directory, or save it to the database. If you pass a reference to a non-existent upload to an upload command, OK is set to zero and A4D_Error is set to -43 (File Not Found).
190
Chapter 11
Command Reference
File Uploads
Active4D v5
Upload Auto-Deletion
If an error occurs during script execution, you may lose track of uploads from the current request. To prevent the accumulation of orphaned uploads, uploads are automatically deleted from the Active4D uploads directory when the current script finishes executing, even if there was an error. If want to retain a copy of the upload, you must use the copy upload command to copy the upload out of the Active4D uploads directory, or use the save upload to field command to save the upload to the database before the script finishes executing.
copy upload
copy upload(inReference; inDestPath) Parameter inReference inDestPath Type Text Text
version 2
Discussion This command copies the referenced upload to the directory and filename given by the native or URL-style path inDestPath. If inDestPath is absolute, it is considered a full path. If inDestPath is relative, it is relative to the default directory. If a file already exists with the same path, it is overwritten. If the copy succeeds, OK is set to 1. Otherwise OK is set to zero and A4D_Error contains the error code. As with all document commands, inDestPath must be within either the web root directory or a directory in the safe doc dirs path list in Active4D.ini. For information on document paths, see Document Paths on page 354. For more information on the safe doc dirs path list, see Misusing Document Commands on page 47.
Chapter 11
Command Reference
191
Active4D v5
File Uploads
count uploads
count uploads Number Parameter Result Type Number Description Number of files uploaded
version 2
Discussion This command returns how many files were actually uploaded in the current request. Even though a file field may be on a form, the user may post the form without uploading a file.
version 2
Discussion This command returns the MIME type of the given upload, which is determined by its filename extension. For example, if the uploaded file was called logo.gif this command , will return image/gif . If no such upload exists, an empty string is returned.
version 2
Discussion This command returns the transfer encoding of the given upload, if it was provided by the client browser (which is usually not the case). If a transfer encoding was not provided or no such upload exists, an empty string is returned.
192
Chapter 11
Command Reference
File Uploads
Active4D v5
version 2
Discussion This command returns the filename extension (including the dot) of the given upload. If the upload has no extension or there is no such upload, an empty string is returned.
version 2
Discussion This command returns the filename of the given upload as it exists on the clients machine. If no such upload exists, an empty string is returned. Note: Some browsers return the full path to the remote file, some just return the filename. You can use the filename of command to be sure you have only the filename.
Chapter 11
Command Reference
193
Active4D v5
File Uploads
version 2
Discussion This command returns the size in bytes of the given upload. If no such upload exists, -1 is returned. You can use this to test whether the given file was actually uploaded.
version 2
Description Name of file field on form Full field reference of destination Pointer to destination field Filename extension of file
Discussion This command saves the given upload to the field identified either by a field reference or by a field pointer. If the given upload does not exist, the destination field is not a BLOB field, or if the save fails in any way, OK is set to zero. If the save succeeds, OK is set to 1.
194
Chapter 11
Command Reference
Form Variables
Active4D v5
Form Variables
When a form is posted, Active4D puts the form variable names and their associated values into a collection. You can access this collection in your scripts. The form variables collection is read-only, and follows the same pattern as all read-only collections.
Chapter 11
Command Reference
195
Active4D v5
Form Variables
_form
_form Longint Parameter Result Type Longint Description Iterator reference
version 3.0
form variables
form variables Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the form variables collection. For more information on iterators, see Iterators on page 208.
version 2
Discussion This command searches the form variables collection for the item with the key inKey. If * is passed, inKey may contain 4D wildcard characters and they will be honored in the search. If the item is found, True is returned, otherwise False.
196
Chapter 11
Command Reference
Form Variables
Active4D v5
version 2
Description Key of form variable to retrieve Index of multiple-choice list value to retrieve Value of form variable or ""
Discussion This command searches the form variable collection for the item with the key inKey. If the item is found and an index is not specified, the items value is returned. If the item value is an array of multiple choices, the first multiple-choice value is returned. Note that this behavior is different than using the syntax:
$value := _form{"multiple_choice_field"} // Returns longint
When using the collection indexing syntax, a reference to an array with no index returns the array itself, which when assigned results in the current element of the array, which is a longint. If the item is found and an index is specified, the given multiple choice value is returned. If the index is out of range, an error is generated and execution is aborted. If the item is not found, an empty string is returned. Note: For scalar values this command has been superceded by the simpler syntax: _form{inKey} or _form{inKey}{inIndex}
version 2
Discussion This command searches the form variables collection for the item with the key inKey. If outArray is defined but is not a string or text array, an error is generated and execution is aborted. If outArray was not defined, it is created as a text array.
Chapter 11
Command Reference
197
Active4D v5
Form Variables
If the item is found and has multiple-choice values in an array, outArray is set to a copy of the multiple-choice values. If the item is found and its value is not an array of multiple-choice values, outArray is set to a single element containing the form variable value. If the item is not found, outArray is resized to zero elements. Note: This command is not really necessary, as you can directly refer to a multiplechoice array with the syntax: _form{inKey} For more information see Referencing Collection Values on page 96.
version 2
Discussion You use this command to check how many values were selected in a multiple-choice list on a form. This command searches the form variables collection for the item with the key inKey. If the item is found and has multiple-choice values in an array, the size of the array is returned. If the item is found and its value is not an array of multiple-choice values, 1 is returned. If the item is not found, zero is returned.
198
Chapter 11
Command Reference
Form Variables
Active4D v5
version 2
Description Receives the collection keys Receives the collection values Indicates a filter is being used Keys are matched against this Concatenation of keys and values
Text Text
Discussion This command has two forms. The first form fills outKeys and outValues with all of the keys and values in the form variables collection. If a value is a multiple-choice array, the first element of the array is put into the outValues array. If outKeys was not defined, it is created as a string array. If outValues was not defined, it is created as a text array. If outKeys is defined but is not a string or text array, an error is generated an execution is aborted. The second form of the command returns a concatenation of the form variables in the form key1=value1;key2=value2 suitable for use as a query string. If a form variable is a , multiple-choice array, all of the array values are included in the concatenation. The keys and values are converted to UTF-8 and URL encoded. You may optionally pass in a string which will be matched against items whose key matches the string. Wildcards are allowed in the filter string. To include items that match the filter, prefix it with +. To exclude items that match the filter, prefix it with -. If there is no prefix, it is assumed to be an inclusion filter.
version 2
Discussion This command returns the number of items in the form variables collection.
Chapter 11
Command Reference
199
Active4D v5
Globals
Globals
In the course of programming a web site, you may need to store application-wide information. Because each HTTP request is handled in a separate process, this means you must have storage that is accessible across processes. You could define interprocess variables in 4D and access them in Active4D. However, this means you must modify the database if you need more interprocess variables in your web site. The whole premise of Active4D is to insulate the database from changes to your web site, so this is not the optimal solution. Active4D provides a special global collection which can be accessed in any Active4D script. By using this collection, you no longer need to use 4D interprocess variables.
Note that in the On Session End method, the globals are not being locked. Active4D automatically locks the globals within the set global command, so for a single set global call it is not necessary to lock the globals.
200
Chapter 11
Command Reference
Globals
Active4D v5
In general, you should lock the globals only when necessary and for as few lines of code as possible. While they are locked, any other processes that try to access the globals will be suspended. If this happens often enough it can have an adverse effect on the performance of your web site. Note: To prevent a potential deadlock condition, Active4D releases the globals lock at the end of script execution and at the end of the following special methods: On Application Start, On Application End, On Session Start, On Session End
Chapter 11
Command Reference
201
Active4D v5
Globals
globals
globals Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the global collection. For more information on iterators, see Iterators on page 208.
globals has
globals has(inKey) Boolean Parameter inKey Result Type Text Boolean Description Key of item to test True if key is in collection
version 2
Discussion This command searches the globals collection for the item with the key inKey. If the item is found, True is returned, otherwise False.
get global
get global(inKey {; inIndex}) <any> Parameter inKey inIndex Result Type Text Longint <any>
version 2
Description Key of global value to retrieve Index of array element to retrieve Value of global or ""
Discussion This command searches the globals collection for the item with the key inKey. If the item is found and inIndex is not specified, the items value is returned. If the item value is an array, an empty string is returned. If the item is found and an index is specified, the given array element is returned. If the index is out of range, an error is generated and execution is aborted.
202
Chapter 11
Command Reference
Globals
Active4D v5
If the item is not found, an empty string is returned. Note: For scalar values this command has been superceded by the simpler syntax: globals{inKey} or globals{inKey}{inIndex}
version 2
Discussion This command searches the global collection for the item with the key inKey. If outArray is not an array, an error is generated and execution is aborted. If the item is found and its value is an array, outArray receives a copy. If outArray has not yet been defined, it is created with the same type as the source array. If the item is found and its value is not an array, an error is generated and execution is aborted. If the item is not found, outArray is resized to zero. If outArray has not yet been defined, it is created as a text array. Note: There is no longer any need to copy a globals array just to manipulate it. You should use the simpler syntax: globals{inKey} The resulting value may be used with all of the array commands such as append to array and DELETE ELEMENT.
Chapter 11
Command Reference
203
Active4D v5
Globals
version 2
Discussion This command searches the global collection for the item with the key inKey. If the item is found and its value is an array, the size of the array is returned. If the item is found and its value is not an array, an error is generated and execution is aborted. If the item is not found, zero is returned. Note: This command has been superceded by the simpler syntax: Size of array(globals{inKey})
version 2
If the item is not found, an empty iterator is returned. For information on empty iterators, see Iterating Over a Collection on page 98.
204
Chapter 11
Command Reference
Globals
Active4D v5
version 2
Discussion This command fills outKeys with all of the keys in the global collection. If outKeys has not yet been defined, it is created as a string array. If outKeys is defined but is not a string or text array, an error is generated an execution is aborted.
set global
set global(inKey; inValue {; inKeyN; inValueN | inIndex}) Parameter inKey inValue inIndex Type Text <any> Longint
version 2
Description Key of collection item to store Value to set for the given item Index of array element to set
Discussion This command searches the global collection for the item with the key inKey. If the item is found and its value is not an array, you may pass more than one key/value pairs to set multiple items at once. If the item is found and its value is an array, you may pass an index to set an element of the array. If the item is found and an index is not specified, the items value is replaced with inValue. If the item is found, its value is an array, and an index is specified, the given array element is set. If the index is out of range or the type of inValue is not assignment-compatible with the array, an error is generated and execution is aborted. If the item is not found and an index is not specified, a new item is added to the collection with the given keys and values. If the item is not found and an index is specified, an error is generated and execution is aborted. Note: For scalar values this command has been superceded by the simpler syntax: globals{inKey} := inValue or globals{inKey}{inIndex} := inValue
Chapter 11
Command Reference
205
Active4D v5
Globals
version 2
Description Key of collection item to set Array to set for the given item
Discussion This command searches the global collection for the item with the key inKey. If inArray is not an array, an error is generated and execution is aborted. If the item is found, its value is replaced with inArray. If the item is not found, a new item is added to the collection with the given key and array. Note: This command has been superceded by the simpler syntax: globals{inKey} := inArray
count globals
count globals Longint Parameter Result Type Longint
version 2
Discussion This command returns the number of items in the global collection.
206
Chapter 11
Command Reference
Globals
Active4D v5
delete global
delete global(inKey) Parameter inKey Type Text
version 2
Discussion This command searches the global collection for the item with the key inKey. To delete more than one item, you may use a wildcard in the key. All items that match will be removed from the collection.
lock globals
lock globals
version 2
Discussion This command locks the global collection such that no other processes may access it. This is the equivalent of using an interprocess semaphore in 4D. For information on globals locking, see Locking and Unlocking the Globals on page 200.
unlock globals
unlock globals
version 2
Discussion This command unlocks the global collection so that other processes may access it. This is the equivalent of using an interprocess semaphore in 4D. For information on globals locking, see Locking and Unlocking the Globals on page 200.
Chapter 11
Command Reference
207
Active4D v5
Iterators
Iterators
As with arrays, it is frequently useful or necessary to iterate over the contents of a collection. With arrays this is easy; you just use a For loop and index into the array to access a specific element. Collections, on the other hand, are not necessarily stored in such a way that a numeric index can efficiently be used to access a particular item. Thus it is necessary to provide another mechanism, known as iteration. Iteration means that you start at the beginning of a collection and advance one item at a time towards the end of the collection. At each step the key and value of the current item can be retrieved. This process is known as iterating over a collection.
In the example above, the collection being iterated over is the form variables collection. Within each pass through the loop, $key is set to the key of the current item, and $value is set to the value of the current item. If the items value is an array, $value receives a copy of the array.
Using Iterators
An iterator is represented by a Longint and can be thought of as a special kind of pointer. When an iterator is first created, it points at the first item in a collection. Given an iterator, you can retrieve the key or value of the item it points to and advance to the next item. Of course, you need to know when you have reached the end of the collection, so iterators also provide a way of telling if there are more items left. The basic template for iterating over a collection looks like this:
$it := <get an iterator command> while (more items($it)) $key := get item key($it) $value := get item value($it) next item($it) end while
Pretty simple. You can also test the type of an items value in case it might be an array, and get the items array if it is.
208
Chapter 11
Command Reference
Iterators
Active4D v5
Iterator Validity
Active4D tests the validity of the iterator passed to each of the iterator commands. If the iterator is not valid, an error is generated and execution is aborted. Thus you do not have to worry about crashing the server because of a bad iterator. All iterators become invalid when execution of a script ends. Warning: If you delete or add an item in a collection, any iterators for that collection will no longer be valid. Thus you should not attempt to delete or add items while iterating over a collection.
Chapter 11
Command Reference
209
Active4D v5
Iterators
version 3.0
Description Collection handle or iterator Receives the item key Receives the item value
Discussion For a full discussion of for each/end for each, see for each/end for each on page 220.
more items
more items(inIterator) Boolean Parameter inIterator Result Type Longint Boolean
version 2
Discussion This command returns True if there are more items in the collection to be iterated.
next item
next item(ioIterator) Parameter ioIterator Type Longint Description Iterator
version 2
Discussion This command advances the iterator to the next item in the collection.
210
Chapter 11
Command Reference
Iterators
Active4D v5
version 2
Discussion This command returns the key of the item currently pointed to by the iterator.
version 2
Discussion This command returns the value of the item currently pointed to by the iterator. If the value is an array, the current value of the array is returned.
version 2
Discussion This command returns the type of the item currently pointed to by the iterator.
Chapter 11
Command Reference
211
Active4D v5
Iterators
version 2
Discussion This command returns the array value of the item currently pointed to by the iterator. If the iterator is not currently pointing at an item with an array value, an error is generated and execution is aborted.
is an iterator
is an iterator(inIterator) Boolean Parameter inIterator Result Type Longint Boolean Description Iterator True if a valid iterator
version 2
212
Chapter 11
Command Reference
Language
Active4D v5
Language
Active4D supports every major feature of the 4D language. In addition, it extends the language to make code writing more efficient. You should especially learn to use the choose command, as it is tremendously useful.
Chapter 11
Command Reference
213
Active4D v5
Language
call 4d method
call 4d method(inMethodName {;inParam1 {;inParamN}}) <any> Parameter inMethodName inParam1..N Result Type Text <any> <any> Description Name of method to call Method parameters Value returned by method
version 1
Discussion This command executes the given 4D method, passing any parameters which follow the method name. It is critical that the parameters you pass are compatible with the parameter declaration in the 4D method. If the method returns a value, it may be ignored. Note: The primary purpose of this command is to allow indirect method calls. Under normal circumstances this command is unnecessary, as you can call 4D methods directly with the same syntax as you would in 4D. If inMethodName does not specify an existing 4D method, an error is generated and execution is aborted. For more on the purpose and use of this command, see Indirect Method Calls (aka Poor Man's method pointers) on page 95.
call method
call method(inMethodName {;inParam1 {;inParamN}}) <any> Parameter inMethodName inParam1..N Result Type Text <any> <any> Description Name of method to call Method parameters Value returned by method
version 1
Discussion This command executes the given Active4D method, passing any parameters which follow the method name. If the method returns a value, it may be ignored. Note: The primary purpose of this command is to allow indirect method calls. Under normal circumstances this command is unnecessary, as you can call Active4D methods directly with the same syntax as you would a 4D method.
214
Chapter 11
Command Reference
Language
Active4D v5
You may specify a library method by using the library.method syntax, just as you would if you were directly calling the method. If inMethodName does not specify an existing Active4D method, an error is generated and execution is aborted. Normal rules for parameter passing to Active4D methods apply to this command. For more information on calling Active4D methods, see Chapter 8, Methods.
choose
choose(inCondition; trueExpression; falseExpression) <any> Parameter inCondition trueExpression falseExpression Result Type Boolean <any> <any> <any>
version 2
Description Determines which expression to evaluate Expression to evaluate if inCondition is True Expression to evaluate if inCondition is False trueExpression or falseExpression
Discussion This command evaluates the Boolean expression inCondition. If the expression evaluates to True, the command evaluates and returns the result of trueExpression. If the expression evaluates to False, the command evaluates and returns the result of falseExpression. This command is basically a way of performing an inline If/Else/End if. Used properly, it can greatly streamline your code. For example, suppose you are building a table with a list of records. If a table cell has no data at all, some browsers will not display the cell as empty, but rather as non-existent. To prevent this, you insert a non-breaking space ( ) in the cell.
Chapter 11
Command Reference
215
Active4D v5
Language
Without the use of choose, your code would look something like this:
<table> <% for ($i; 1; records in selection([contacts])) goto selected record([contacts]; $i) %> <tr> <td> <% if (length([contacts]name) = 0) write(" ") else write([contacts]name) end if %> </td> </tr> <% end for %> </table>
Note that we have streamlined even further by using the = operator as a synonym for write. For more information on this use of =, see Response Buffer on page 272. Heres another example where choose comes in handy: setting radio buttons. To set a radio button in HTML, you must add the word checked to the radio buttons tag. Ordinarily, this would require a separate test for each radio button declaration, like this:
<input type="radio" name="f_radio" value="1" <% if ([contact]rating = 1) write("checked") end if %> />Good <br /> <input type="radio" name="f_radio" value="2" <% if ([contact]rating = 2) write("checked") end if %> />Better <br /> <input type="radio" name="f_radio" value="3" <% if ([contact]rating = 3) write("checked") end if %> />Best<br />
216
Chapter 11
Command Reference
Language
Active4D v5
Yuck. This would probably lead you to write a library method something like this:
method "makeRadio"($inName; $inValue; $inChecked) write('<input type="radio" name="$inName" value ="inValue"') if ($inChecked) write(" checked") end if write(" />") end method
This is better in one sense, but worse in another; because you have embedded the radio button HTML in a method, you lose the ability to view and edit the checkbox in an HTML editor. Remember, the whole point of Active4D is to embed your code in HTML, not the other way around. Using choose, you can have the best of both worlds, like this:
<input type="radio" name="f_radio" <%=choose([contact]rating = 1; <br /> <input type="radio" name="f_radio" <%=choose([contact]rating = 2; <br /> <input type="radio" name="f_radio" <%=choose([contact]rating = 2; value="1" "checked"; "")%> />Good value="1" "checked"; "")%> />Better value="1" "checked"; "")%> />Best
define
define(inName; inValue) Parameter inName inValue Type Identifier <any>
version 1
Description A name for the constant The value to assign to the constant
Discussion This keyword defines a new named constant. The name must conform to the rules for 4D process variables. The value can be any valid expression. Named constants have scope, like local variables. Constants defined outside of a library are global in scope, and may be accessed anywhere, including within the body of methods. Constants defined within libraries are scoped to the library, like library methods. Library constants are accessible to all methods in the library without using the library name. Outside of the library, library constants are accessible by using <library>.<constant> notation, where <library> is the library name and <constant> is the constant name, or
Chapter 11
Command Reference
217
Active4D v5
Language
simply by using <constant> if its name does not clash with any other name in the current scope. If used within a library definition, the define command must appear after between the library and end library keywords, but outside of any method definitions. It is an error to define a constant within the body of a method. If a library constant referred to within a library method has the same name as a global constant, the library constant is used. However, if you refer to a constant outside of a library method that is defined in more than one imported library, or defined in an imported library and the global scope, an error is generated because Active4D cannot disambiguate the constant reference. Thus, if a global constant has the same name as an imported library constant, it will no longer be accessible. The define command is useful anywhere you would normally want to use a named constant within 4D, but you have not created one. For example, suppose you have a Longint field called [Sales_Leads]Rating which classifies a sales lead according to the following values: Value 1 2 3 4 Description Cold Warm Hot Nuclear
If you have not defined 4DK# named constants for these values, it would be nice to refer to them by names instead of numbers. You could create a file called constants.a4d which contained the following code:
<% define(kSalesLead_Cold; 1) define(kSalesLead_Warm; 2) define(kSalesLead_Hot; 3) define(kSalesLead_Nuclear; 4) %>
Within several scripts you need to use those constants. You cannot use include, because it is an error to define the same constant more than once. This is where require comes in. By using require before the code that uses the constants, like this:
<% require("constants.a4d") query([sales_leads];[sales_leads]rating = kSalesLead_Nuclear) // and so on %>
you can ensure they are defined without worrying about whether or not they have already been defined within the current script execution.
218
Chapter 11
Command Reference
Language
Active4D v5
EXECUTE
EXECUTE(inText {; *}) <any> Parameter inText * Result Type Text * <any>
Discussion This command can be used like the standard EXECUTE command in 4D, which is limited to executing a single line of code. Active4D extends the EXECUTE command to allow execute of an entire block of code, including control structures like loops and If/Else/End if. This allows you to use techniques such as storing scripts in the database to prevent manipulation by the end user, like this:
query([scripts];[scripts]name="query customer by name") execute([scripts]text)
Active4D also extends EXECUTE by allowing you to return a value using the return keyword within the executed text, like this:
$text := "return (size of array(%s))" % $arrayName $size := execute($text)
If the option * argument is passed, inText is treated as HTML with embedded Active4D code instead of raw Active4D code. Effectively this is the same as an include, but the code to include is passed directly into the command.
execute in 4d
execute in 4d(inText {; *}) Parameter inText * Type Text * Description Text to execute Expect a result
version 4.0
Discussion This command executes inCode within 4D, and is subject to all of the restrictions of 4D's EXECUTE command.
Chapter 11
Command Reference
219
Active4D v5
Language
If * is passed, the result of the executed code can be returned as the result of the command. If there is an error in the parsing or execution of inCode, Active4D throws a syntax error. In conjunction with the ability to create process/interprocess variables within Active4D, this command relieves you of the need to write wrapper 4D methods to implement commands that are not supported natively within Active4D. For example, lets assume you need to use 4Ds Square root command. Instead of writing a method to call the command, you can do this:
$num := 7 $root := execute in 4d("Square root(%d)" % ($num); *)
version 3.0
Description Collection handle or iterator Receives the item key Receives the item value
Array to iterate over Receives the current array element Receives the current array index
Text to iterator over Receives the current character Receives the current character index
Table Number
Discussion This control structure is a generalized sequence iterator, where a sequence is defined as a sequence of values, including collections, arrays, strings and selections. Depending on the sequence which is passed as the first argument, for each takes different arguments. Each for each must be balanced with a corresponding end for each.
220
Chapter 11
Command Reference
Language
Active4D v5
Collections If a collection reference is passed as the first argument, for each iterates over the items in the collection. In the body of the loop, outKey contains the key of the current collection item, and outValue (if passed) contains a copy of the current collection items value. If the item value is an array, outValue receives a copy of the array. Example
for each(form variables; $key; $value) writebr($key + "=" + $value end for each $c := new collection $c{"name"} := "Dave" $c{"age"} := 31 for each($c; $key) writebr('$key=$c{$key}') end for each
Arrays If an array is passed as the first argument, for each iterates over the elements in the array. In the body of the loop, outValue contains the current array element, and outIndex (if passed) contains the index of the element. Example
for each($myArray; $value; $i) writebr('$i: $value') end for each // above code is equivalent to: for($i; 1; size of array($myArray)) writebr('$i: $myArray{$i}') end for
Strings If text is passed as the first argument, for each iterates over the characters in the text. In the body of the loop, outCharacter contains the current character, and outIndex (if passed) contains the index of the character.
Chapter 11
Command Reference
221
Active4D v5
Language
Example
$s := "foo" for each($s; $char; $i) writebr('[[$i]]: $char') end for each // above code is equivalent to: for($i; 1; length($s)) writebr('[[$i]]: $s[[$i]]') end for
Selections If a table reference is passed as the first argument, for each iterates over the records in the current selection of the table. In the body of the loop, outIndex (if passed) contains the selected record index. Example
for each([contacts]; $i) writebr('$i. [contacts]fullname') end for each // above code is equivalent to: first record([contacts]) while(not(end selection([contacts]))) writebr("%d. %s" % (selected record number([contacts]); \\ [contacts]fullname)) end while
Get pointer
Get pointer(inName ) Pointer Parameter inName Result Type Text Pointer Description Name of variable Pointer to variable
version 1 modified v5
Discussion This command functions exactly like the Get pointer command in 4D, with the addition that you may use <> with an interprocess variable name on Mac OS X.
222
Chapter 11
Command Reference
Language
Active4D v5
global
global(localVar {; localVarN} | *) Parameter localVar | * Type Local Variable | *
version 1
Discussion When you call an Active4D method, the method has its own local variables in a separate scope, just as in 4D. If you want to access or modify local variables outside of the method, ordinarily you would pass the variables to the method as by-value or by-reference parameters. However, there are times when it is necessary to have direct access to local variables outside of the method. The action of this command depends on where it is used and whether or not the named variables already exist.
3 If this command is used in the global scope, it does nothing. 3 If this command is used within a method and localVar exists in the global scope, it will
be accessible within the scope of the method.
3 If this command is used within a method and localVar does not exist in the global
scope, if it is defined within the method it will be in the global scope.
3 If this command is used within a method and you pass * instead of one or more
variable names, all locals in the global scope will be accessible within the method and all locals defined within the method will be in the global scope. Variables created with set local are also affected by the use of this command. In general you should avoid using the form global(*), because you are likely to create variables in the global scope unintentionally. Example In this example, the variable $foo is defined in the global scope before calling the method foobar. Because $foo is declared as global within foobar, it is accessible within that method. Because $bar is declared global before being defined, it is then accessible in the global scope outside of foobar, but not until after foobar executes.
method "foobar" global($foo; $bar) writebr($foo) end method $foo := "foo" foobar writebr($bar)
Chapter 11
Command Reference
223
Active4D v5
Language
import
import(inLibName {; *}) { Boolean } Parameter inLibName Result Type Text Boolean
Discussion This command loads an Active4D library. For a full discussion of library importing, see Importing Libraries on page 114. If the optional * is passed, no error is generated if the library is not successfully imported, and a Boolean value is returned to indicate the success of the import. This allows you to attempt to import optional libraries.
include
include(inPath) Parameter inPath Type Text Description Path of file to include
version 1
Discussion This command includes the file specified by inPath. The path may be absolute or relative. An absolute path will be relative to the web root directory, a relative path will be relative to the currently executing file. To include a file outside of the web root, you must either create an alias within the web root to the include file or the directory in which the include file lives, or use relative motion within the include path. Here are some examples:
// Here we are using relative motion in the include path. // Note that ".inc" does NOT have to be registered as an // executable extension, because the include command doesn't // check that. include("/../includes/foobar.inc") // Here we have created an alias called "includes" within the // web root which points to a directory outside the web root. include("/includes/foobar.inc")
For more information on includes, see Including Other Files on page 93.
224
Chapter 11
Command Reference
Language
Active4D v5
include into
include into(inPath; outBuffer) Parameter inPath outBuffer Type Text Text/BLOB
version 2
Discussion This command is identical to the include command, but it temporarily makes outBuffer the response buffer for the duration of the include (and any nested includes). This is extremely useful when you want to create dynamic output that will go somewhere other than the browser. For example, if you want to generate an invoice and email it to a client, you could do the following: 1 2 3 Create a nicely formatted HTML invoice, embedding Active4D code to fill in the details of the invoice. Use include into to dynamically generate the invoice and place the result in a text variable. Call a4d.utils.sendMail to email the generated invoice as the email body.
outBuffer may be a scalar (non-array) variable, an element of a string or text array, or a reference to a collection item. If not, an error is generated and execution is aborted. If an error occurs in the code of the included file (or any nested includes), outBuffer is left untouched and the error message is placed in the normal response buffer for display in the browser.
longint to time
longint to time(inLong) Time Parameter inLong Result Type Longint Time Description Value to convert to a time Converted value
version 1
Discussion This command converts a Longint value into a Time value. Unless you use a compiler declaration, Active4Ds variables are variant in their type. To assign a Longint to a variant variable as a Time you must use this command. This is
Chapter 11
Command Reference
225
Active4D v5
Language
specially useful when you are storing Times in a Longint array and you want to retrieve the elements as Times. Note: You could also use C_TIME to fix a variables type to Time and assign a Longint to it. This would do type conversion for you.
method exists
method exists(inMethodName {; outLibName}) Boolean Parameter inMethodName outLibName Result Type Text Text Boolean
version 4.0
Description Name of method to check Name of methods library True if method exists
Discussion This command determines if the method with the name inMethodName exists. If inMethodName is a fully qualified library.method name, the library is imported if necessary and then that library is checked for the given method name. If inMethodName is not fully qualified, only the currently imported libraries are checked for the given method name. If outLibName is passed in, it receives the name of the library in which the method is found, or an empty string if the method is not found. If inMethodName is the name of an inline method, outLibName will be global .
226
Chapter 11
Command Reference
Language
Active4D v5
nil pointer
nil pointer Pointer Parameter Result Type Pointer Description A nil pointer
version 4.0
Discussion This command returns a nil pointer (big surprise). It is designed to be used in those cases where you want to specifically pass a nil pointer to a method, instead of using the standard trick:
// old way c_pointer($nil) doSomething($nil) // new way doSomething(nil pointer)
redirect
redirect(inURL {; inIsPermanent}) Parameter inURL inIsPermament Type Text Boolean
version 1 modified v5
Discussion This command issues a true HTTP redirect to the specified URL, generating the necessary response status, headers and content based on the HTTP version of the client. inURL may be a full URL to an external server (beginning with http://), an absolute path, or a relative path. Absolute paths are considered to be relative to the web root. Relative paths are relative to the file which contains the redirect command. If inIsPermanent is passed and is True, a 301 Moved Permanently status is returned to the browser instead of 303 See Other. As soon as redirect is executed, the script immediately stops execution and returns control to the shell. Thus redirect will be the last command within a flow of execution.
Chapter 11
Command Reference
227
Active4D v5
Language
require
require(inPath) Parameter inPath Type Text Description Path of file to include
version 1
Discussion This command is identical to the include command, but if the given file has already been loaded with the require command within the current script execution, it will not be loaded again. The primary use for this command is to create a file of defined constants which you want to reference throughout your pages. For an example of this usage, see define on page 217.
RESOLVE POINTER
RESOLVE POINTER(inPointer; outName; outTableNum; outFieldNum) Parameter inPointer outName outTableNum outFieldNum Type Pointer Text Number Number
version 1 modified v5
Description Pointer to resolve Receives referent name Receives table number/array index Receives field number
Discussion This command performs the same function as the RESOLVE POINTER command in 4D. Unlike 4D however, if inPointer points to an interprocess variable, outName will always be prefixed with <> even on Mac OS X. ,
228
Chapter 11
Command Reference
Language
Active4D v5
sleep
sleep(inTicks) Parameter inTicks Type Number Description Ticks to delay
version 1
The difference is that it will actually delay, whereas the equivalent 4D code, when executed from a web process, will do nothing.
throw
throw(inMessage) Parameter inMessage Type Text Description Error message
version 3.0
Discussion This command generates an Active4D runtime error with the given message. This is useful for debugging purposes.
time to longint
time to longint(inTime) Longint Parameter inTime Result Type Time Longint
version 1
Discussion This command converts a Time value into a Longint value. Unless you use a compiler declaration, Active4Ds variables are variant in their type. To assign a Time to a variant variable as a Longint you must use this command. This is
Chapter 11
Command Reference
229
Active4D v5
Language
specially useful when you are storing Times in a Longint array and you want to set the elements as Times. Note: You could also use C_LONGINT to fix a variables type to Longint and assign a Time to it. This would do type conversion for you.
230
Chapter 11
Command Reference
Math
Active4D v5
Math
Active4D adds several utility commands that solve simple but common math problems with a minimum of code.
Chapter 11
Command Reference
231
Active4D v5
Math
max of
max of(inValue1; inValue2) Number Parameter inValue1 inValue2 Result Type Number Number Number Description Number to compare Number to compare Greater of the two values
version 1
Discussion This command compares inValue1 to inValue2. The greater of the two values is returned.
min of
min of(inValue1; inValue2) Number Parameter inValue1 inValue2 Result Type Number Number Number Description Number to compare Number to compare Lesser of the two values
version 1
Discussion This command compares inValue1 to inValue2. The lesser of the two values is returned.
random between
random between(inMin; inMax) Number Parameter inMin inMax Result Type Number Number Number
Description Minimum number to return Maximum number to return Random number between inMin and inMax inclusive
Discussion This command returns a random number between inMin and inMax inclusive. If inMin > inMax the result is undefined. Both inMin and inMax may be numbers in the full range of a 4D Real.
232
Chapter 11
Command Reference
Pictures
Active4D v5
Pictures
Active4D allows you to read, manipulate, convert and write pictures to disk and to the response buffer. Using this capability, you can programmatically create and serve graphics on the fly. The following 4D picture commands are supported in Active4D: Picture size PICTURE PROPERTIES READ PICTURE FILE WRITE PICTURE FILE GET PICTURE FROM LIBRARY As with all document commands, READ PICTURE FILE and WRITE PICTURE FILE have their paths checked against the list of safe document directories. In addition to these commands, you may also use the following operators on pictures: + / += /= horizontal concatenation vertical concatenation horizontally concatenate and assign vertically concatenate and assign
Chapter 11
Command Reference
233
Active4D v5
Pictures
This is not actually a command, but rather a script file that acts like a method. It is designed to be called by making it the image source in an HTML <img> tag. You pass parameters to the script through the query string. This script can dynamically load images from four different sources:
3 Picture library 3 Database 3 Disk file 3 Active4D method call 3 4D method call
In addition, you may request that the image be turned into a thumbnail of a given size, and you may request the image in PNG, JPEG or GIF format. These two features are controlled by two optional query string parameters: Parameter size width height format Description Desired pixel width/height Desired pixel width Desired pixel height png , jpg or gif
If size, width or height is passed, the image will be scaled proportionally to the given size. If format is passed, the default format will be overridden and the image will be returned in the requested format.
If this query parameter is passed, the picture with the given numeric id (if the first character is a digit) or name will be returned if it exists. By default the picture will be converted to PNG.
234
Chapter 11
Command Reference
Pictures
Active4D v5
If these three query parameters are passed, a query is done on qry_field for qry_value, and if one or more records results, the value of img_field from the first record is used. The field referenced by qry_field must be either Alpha or Longint (its supposed to be an id field). By default the picture will be converted to JPEG.
If these two query parameters are passed, the record with the given number is loaded, and if such a record exists, the value of img_field is used. By default the picture will be converted to JPEG.
If this query parameter is passed, the image at the given location will be returned. By default the image will take the format of the original, depending on the filename extension. If the filename extension is not .png or .gif it defaults to JPEG format. , This use of image.a4d is primarily useful if you want to create a thumbnail, because otherwise it would be much more efficient to reference the image directly.
Chapter 11
Command Reference
235
Active4D v5
Pictures
If the method query parameter is passed, the Active4D method with the given name will be called. The method should have the following signature:
method "getImage"($inParams; &$ioFormat) // Get a picture into $pict. You can optionally // set the format by setting $ioFormat. return ($pict) end method
Of course you may change getImage to whatever you like. If you need to pass multiple parameters to the method, you can pack them together with concat (do not use ; as the separator, use a character such as |),and then unpack them with slice string or split string in the method.
If the method4d query parameter is passed, the 4D method with the given name will be called. The method should have the following signature:
`getImage($inParams) C_TEXT($1) C_PICTURE($0) `Get a picture somehow, assign to $0
Of course the name of the method may be whatever you like. If you need to pass multiple parameters to the method, you can pack them together with concat and then unpack them in the 4D method.
Examples
Get a picture from the picture library in JPEG format:
<img src="/image.a4d?id=100;format=jpg" alt="image" />
236
Chapter 11
Command Reference
Pictures
Active4D v5
Get an image from a table via a query, making a thumbnail 48 pixels in size:
<% $qry := build query string(""; "img_field"; "[images]image"; \\ "qry_field"; "id"; \\ "qry_value"; 100; \\ "size"; 48) %> <img src="/image.a4d<%=$qry%>" alt="image" />
write gif
write gif(inPicture {; inWidth {; inHeight}}) Parameter inPicture inWidth inHeight Type Picture Number Number
Description Picture to convert to GIF format Pixel width or scaling percentage Pixel height or scaling percentage
3 Scales inPicture according to inWidth/inHeight if passed 3 Converts inPicture into a GIF graphic
Chapter 11
Command Reference
237
Active4D v5
Pictures
3 Replaces the current contents of the response buffer with the graphic 3 Sets the content type of the response to image/gif
If inWidth is nonzero and inHeight is zero or is omitted, the height will be scaled proportionally to inWidth. If inWidth is zero and inHeight is nonzero, the width will be scaled proportionally to inHeight. If inWidth or inHeight is a positive number, it is treated as an absolute pixel size. If inWidth or inHeight or negative, they are treated as scaling factors, where .5=50%, 2=200%, etc. Note: 4Ds GIF conversion routines are optimized for pictures with 256 colors or less. Pictures with more colors will be converted with noticeable banding and dithering artifacts.
write jpeg
write jpeg(inPicture {; inWidth {; inHeight}}) Parameter inPicture inWidth inHeight Type Picture Number Number
version 2 modified v5
Description Picture to convert to JPEG format Pixel width or scaling percentage Pixel height or scaling percentage
3 Scales inPicture according to inWidth/inHeight if passed 3 Converts inPicture into a JPEG graphic 3 Replace the current contents of the response buffer with the graphic 3 Set the content type of the response to image/jpeg
If inWidth is nonzero and inHeight is zero or is omitted, the height will be scaled proportionally to inWidth. If inWidth is zero and inHeight is nonzero, the width will be scaled proportionally to inHeight. If inWidth or inHeight is a positive number, it is treated as an absolute pixel size. If inWidth or inHeight or negative, they are treated as scaling factors, where .5=50%, 2=200%, etc. Note: As of v5, 4Ds built in picture conversion is being used to convert to JPEG, and the result is lower quality than what Active4D v4.x produced. PNG is recommended as the picture format for images that are not photographs.
238
Chapter 11
Command Reference
Pictures
Active4D v5
write jpg
write jpg(inPicture {; inWidth {; inHeight}}) Parameter inPicture inWidth inHeight Type Picture Number Number
version 2 modified v5
Description Picture to convert to JPEG format Pixel width or scaling percentage Pixel height or scaling percentage
write png
write png(inPicture {; inWidth {; inHeight}}) Parameter inPicture inWidth inHeight Type Picture Number Number
Description Picture to convert to PNG format Pixel width or scaling percentage Pixel height or scaling percentage
3 Scales inPicture according to inWidth/inHeight if passed 3 Converts inPicture into a PNG graphic 3 Replace the current contents of the response buffer with the graphic 3 Set the content type of the response to image/png
If the original image within inPicture was a PNG image with an alpha channel, the alpha channel is preserved in the output of this command. If inWidth is nonzero and inHeight is zero or is omitted, the height will be scaled proportionally to inWidth. If inWidth is zero and inHeight is nonzero, the width will be scaled proportionally to inHeight. If inWidth or inHeight is a positive number, it is treated as an absolute pixel size. If inWidth or inHeight or negative, they are treated as scaling factors, where .5=50%, 2=200%, etc.
Chapter 11
Command Reference
239
Active4D v5
Queries
Queries
Active4D implements the extended (but undocumented) syntax of the QUERY, QUERY SELECTION and ORDER BY commands.
240
Chapter 11
Command Reference
Queries
Active4D v5
QUERY/QUERY SELECTION
version 2
QUERY/QUERY SELECTION(inTable; inConjunction; inField; inComparator; inValue {;*}) Parameter inTable inConjunction inField inComparator inValue * Type Table Literal string Field Literal string <any> Description Table on which to query "|", "&" or "#" Field on which to query "=", "#", "<", "<=", ">" or ">=" Value to compare against field To defer query
Discussion The extended syntax of these commands puts the field, comparator and value into separate parameters. To dynamically build a query statement, you can build the statement as a string and then pass the string to the EXECUTE command.
ORDER BY
ORDER BY
version 2
Discussion Active4D supports built sorts using multiple ORDER BY statements, in the same way that a built query can be executed. To build a sort, add a * parameter at the end of the statement. This will defer the sort until an ORDER BY statement is executed without a final * parameter. As with built queries, once a deferred ORDER BY statement has been executed, the sort may be executed with the following syntax:
order by([MyTable])
Chapter 11
Command Reference
241
Active4D v5
Query Params
Query Params
When a URL is requested which has a query string, Active4D puts the query parameter names and their associated values into a collection. You can access this collection in your scripts. Note: If the parameter mode configuration option is set to form variables query , parameters will not go into the query params collection, but into the form variables collection. Likewise, if the parameter mode option is set to query params form , variables will go into the query params collection. The query params collection is read-only, and follows the same pattern as all read-only collections.
242
Chapter 11
Command Reference
Query Params
Active4D v5
_query
_query Longint Parameter Result Type Longint Description Iterator reference
version 3.0
query params
query params Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the query params collection. For more information on iterators, see Iterators on page 208.
version 2
Discussion This command searches the query params collection for the item with the key inKey. If * is passed, inKey may contain 4D wildcard characters and they will be honored in the search. If the item is found, True is returned, otherwise False.
Chapter 11
Command Reference
243
Active4D v5
Query Params
version 2 modified v5
Description Key of query param to retrieve Index of multiple-choice list value to retrieve Value of query param or ""
Discussion This command searches the query param collection for the item with the key inKey. If the item is found and an index is not specified, the items value is returned. If the item value is an array of multiple choices, the first multiple-choice value is returned. Note that this behavior is different than using the syntax:
$value := _query{"multiple_choice_value"} // Returns longint
When using the collection indexing syntax, a reference to an array with no index returns the array itself, which when assigned results in the current element of the array, which is a longint. If the item is found and an index is specified, the given multiple choice value is returned. If the index is out of range, an error is generated and execution is aborted. If the item is not found, an empty string is returned. Note: The query param value is URL decoded and converted from UTF-8, so you do not need to perform any decoding.
version 2
Discussion This command searches the query params collection for the item with the key inKey.
244
Chapter 11
Command Reference
Query Params
Active4D v5
If outArray is defined but is not a string or text array, an error is generated and execution is aborted. If outArray was not defined, it is created as a text array. If the item is found and has multiple-choice values in an array, outArray is set to a copy of the multiple-choice values. If the item is found and its value is not an array of multiple-choice values, outArray is set to a single element containing the query param value. If the item is not found, outArray is resized to zero elements.
version 2
Discussion You use this command to check how many values were selected in a multiple-choice list on a form. This command searches the query params collection for the item with the key inKey. If the item is found and has multiple-choice values in an array, the size of the array is returned. If the item is found and its value is not an array of multiple-choice values, 1 is returned. If the item is not found, zero is returned.
Chapter 11
Command Reference
245
Active4D v5
Query Params
version 2 modified v5
Description Receives the collection keys Receives the collection values Indicates a filter is being used Keys are matched against this Concatenation of keys and values
Text Text
Discussion This command has two forms. The first form fills outKeys and outValues with all of the keys and values in the query params collection. If outKeys was not defined, it is created as a string array. If outValues was not defined, it is created as a text array. If outKeys is defined but is not a string or text array, an error is generated an execution is aborted. The second form of the command returns a concatenation of the form variables in the form key1=value1;key2=value2 suitable for use as a query string. If a form variable is a , multiple-choice array, all of the array values are included in the concatenation. The keys and values are converted to UTF-8 and URL encoded. You may optionally pass in a string which will be matched against items whose key matches the string. Wildcards are allowed in the filter string. To include items that match the filter, prefix it with +. To exclude items that match the filter, prefix it with -. If there is no prefix, it is assumed to be an inclusion filter. Note: The keys and values are URL decoded and converted from UTF-8 to Unicode, so you do not need to perform any decoding.
246
Chapter 11
Command Reference
Query Params
Active4D v5
version 2
Discussion This command returns the number of items in the query params collection.
version 3.0
build query string({*;} inQuery; inName; inValue {; inNameN; inValueN}) Text Parameter * inQuery inName inValue Result Type * Text Text <any> Text Description If passed, dont suppress empty values Existing query string to build on Query param name Query param value New query string
Discussion This command is extremely useful for building a query string to add to a URL. It adds the given name/value pairs to inQuery, automatically converting the keys and values to UTF8 and then URL encoding. As of HTML 4.0, the recommended practice for delimiting query parameters is to use a semicolon, not an ampersand (&). Accordingly this is what build query string does. If inQuery is empty, the result will begin with ? If inQuery starts with - it can be . , followed by one or more of the following switches:
3 e - External reference mode: Use this mode if you are passing a query string to a
non-Active4D server that may not understand semicolons as query parameter delimiters. If this switch is set, by default query parameters will be delimited with "&" as required by HTML 4+ for URLs embedded in HTML. If you are building a query string for use in an external redirect, be sure to set the r switch as well.
3 r - Redirect mode: This switch has no effect unless the e switch is set as well, in
which case the query parameter separator will be "&" instead of "&".
3 u - URL encoded mode: It is assumed the query parameter names and values are
already URL encoded, so no encoding is done.
Chapter 11
Command Reference
247
Active4D v5
Query Params
3 a - Append mode: Whether or not inQuery is empty (not including the switches), it
will be considered non-empty. Use this switch to append the results of this command to an existing query string. Note: You do not need to use the a switch when creating a query to pass to fusebox.makeURL or fusebox.handleError. If text follows the switches, there should be another - between the switches and the text. If there are no switches set and inQuery is not empty, the name/value pairs will be appended to inQuery. If the * parameter is not passed, name/value pairs with an empty value will be skipped. If the * parameter is passed, all name/value pairs will be appended to the query string. Examples
$query := build query string(""; \\ "rec"; record number([employees]); \\ "action"; _form{"f_action"}) // $query = "?rec=123;action=edit" redirect("edit_emp.a4d" + $query) // using the e and r switches $query := build query string("-e"; "foo"; 7; "bar"; 13) // $query = "?foo=7&bar=13" $query := build query string("-er"; "foo"; 7; "bar"; 13) // $query = "?foo=7&bar=13" $barValue := url encode query("this is a test") $query := build query string("-u"; "foo"; 7; "bar"; $barValue) // $query = "?foo=7;bar=this+is+a+test" $query := build query string("-p"; "foo"; 7; "bar"; 13) // $query = "foo=7;bar=13" redirect("foobar.a4d?" + $query) $query := build query string("-a"; "foo"; 7; "bar"; 13) // $query = ";foo=7;bar=13" redirect(fusebox.makeURL("foobar.main"; $query))
248
Chapter 11
Command Reference
Regular Expressions
Active4D v5
Regular Expressions
Active4D implements a powerful suite of regular expression commands that allow you to perform complex searches and manipulations on text. Regular expressions are in fact a compact programming language, and as such allow you to perform text manipulations that would take many lines of code to implement.
Pattern Syntax
Regular expressions follow the ICU syntax, which is described here: http://userguide.icu-project.org/strings/regexp Regular expressions in Active4D fully support Unicode. Note: Previous versions of Active4D used the PCRE library for regular expression matching. Although the pattern syntax of PCRE and ICU and very similar, there are some differences, so you should carefully check your regular expression patterns if you are upgrading from v4.x to v5. Regular expression patterns must be enclosed in delimiters, for example a forward slash (/). Any non-alphanumeric Unicode character in the Basic Multilingual Plane (other than backslash) can be used as the delimiter. If the delimiter character is used in the expression itself, it needs to be escaped by a backslash. The ending delimiter may be followed by various modifiers that affect the matching. The pattern modifiers are discussed in detail here (see Flag Options): http://userguide.icu-project.org/strings/regexp#TOC-Flag-Options For examples of the pattern syntax, see the example code for the commands in this chapter.
Chapter 11
Command Reference
249
Active4D v5
Regular Expressions
version 3.0
regex callback replace(inPattern; inSubject; inCallback; outResults {; inLimit}) Parameter inPattern inSubject inCallback outResults inLimit Type Text | String/Text Array Text/BLOB | String/Text Array Text Text | String/Text Array Number Description Search pattern(s) Subject(s) to search Name of method to call Receives the replaced text Limit on number of matches
Discussion This command is almost identical to regex replace, except that instead of replacement parameter, you specify the name of a callback method that will be called once for each match. The method must be an Active4D method which takes a single reference array parameter. The array will contain the matched elements in the subject string, with the entire matched string in element zero and captured subpatterns in subsequent elements. The callback should return the entire replacement string. Note: Internally this command creates a local array called $__a4d_regex_callback_array__, which is passed to the callback method. Be sure not to give any of your local variables this name.
250
Chapter 11
Command Reference
Regular Expressions
Active4D v5
Example Lets say you want to add one year to a bunch of dates.
method "addOneYear"(&$inArray) c_longint($year; $month; $day) $month := num($inArray{1}) $day := num($inArray{2}) $year := num($inArray{3}) $date := add to date(!00/00/00!; $year + 1; $month; $day) return (string($date; MM DD YYYY Forced)) end method /* The pattern followed by followed by followed by followed by followed by followed by looks for the digit 0 or 1, any digit, a forward slash, the digits 0-3, any digit, a forward slash, four digits.
*/ $pattern := "|([01]\d)/([0-3]\d)/(\d{4})|" array text($dates; 0) set array($dates; "08/27/2003"; "03/30/2003") regex callback replace($pattern; $dates; "AddOneYear"; $results) writebr(join array($results; "<br />\n")) // Output is: 08/27/2004 03/30/2004
version 3.0
regex find all in array(inArray; inPattern; outIndexes {; inStartIndex}) Longint Parameter inArray inPattern outIndexes inStartIndex Result Type String/Text Array Text Longint Array Longint Longint Description Array to search What to match in the array Receives the match indexes Where to start searching Index of first matching element
Discussion This command searches inArray for the all elements that match the pattern inPattern. The index of the first matching element is returned, or -1 if no elements match the pattern. The indexes of all matching elements are put in the array outIndexes. outMatches does not have to be defined before using this command.
Chapter 11
Command Reference
251
Active4D v5
Regular Expressions
Example
// Find all elements that start with "foo" or end with "bar" array text($array; 0) set array($array; "one foo"; "two bar"; "fool"; "bart") $index := regex find all in array($array; "/^foo|bar$/"; \\ $matches) writebr(join array($matches; "<br />\n")) // Output is: 2 3
version 3.0
Description Array to search What to match in the array Where to start searching Index of first matching element
command searches inArray for the first element that matches the pattern inPattern. The index of the first matching element is returned, or -1 if no elements match the pattern. Example
// Find the first element that starts with "foo" // or ends with "bar" array text($array; 0) set array($array; "one foo"; "two bar"; "fool"; "bart") $index := regex find in array($array; "/^foo|bar$/") writebr($index) // Output is: 2
252
Chapter 11
Command Reference
Regular Expressions
Active4D v5
regex match
regex match(inPattern; inSubject {; outMatches}) Boolean Parameter inPattern inSubject outMatches Result Type Text Text/BLOB String/Text Array Boolean
Description What to match in the subject The text to search Receives the matches True if any matches were found
Discussion This command searches inSubject for the first match to the regular expression given in inPattern. If a matches are found, True is returned, otherwise False. If inSubject is a BLOB, it is assumed to be in the format UTF8 Text without length. If outMatches is provided, it is filled with the results of the search. $outMatches{0} will contain the text that matched the full pattern, $outMatches{1} will contain the text that matched the first captured parenthesized subpattern, and so on. If outMatches is a local variable (or collection item) and was not defined, it is created as a text array. Example Splitting a URL into constituent parts:
/* The following pattern will split a URL into six parts: 1) "http://" if present 2) hostname 3) "/4dcgi" if present 4) resource path 5) "?" at start of query string if present 6) query string if present */ $pattern := "|^(http://)?([^/]+)(/4dcgi)?([^?]+)(\?)?(.*)|i" $url := "http://www.myserver.com/4dcgi/index.a4d?foo=bar" $found := regex match($pattern; $url; $matches) writebr(join array($matches; "<br />\n"; 0)) // Output is: http://www.myserver.com/4dcgi/index.a4d?foo=bar http:// www.myserver.com /4dcgi /index.a4d ? foo=bar
Chapter 11
Command Reference
253
Active4D v5
Regular Expressions
Notice in the above example that $matches{0} contains the full URL, because that is what matched the full pattern.
version 3.0
Description What to match in the subject The text to search Receives the matches The number of matches made
Discussion This command searches inSubject for the all matches to the regular expression given in inPattern. After the first match, subsequent matches are made starting from the end of the previous match. The number of matches made is returned. If inSubject is a BLOB, it is assumed to be in the format UTF8 Text without length. outMatches is filled with the results of the search. The collection will contain one item for each match, with the keys named from 00001 to the number of matches made. Note: Obviously because of the naming scheme you are limited to 99,999 matches. The contents of each collection item is an array which contains what a call to regex match would return, i.e. $outMatches{$key}{0} will contain the text that matched the full pattern, $outMatches{$key}{1} will contain the text that matched the first captured parenthesized subpattern, and so on. Example Find matching HTML tags:
$pattern := "|(<([\w]+)[^>]*>)(.*)(</\\2>)|" $html := "<b>example: </b><p>this is a test</p>" regex match all($pattern; $html; $matches) for each($matches; $key) $html := join array($matches{$key}; ", "; 0; false; true) writebr($html; ""; A4D Encoding All) end for each // Output is: "<b>example: </b>", "<b>", "b", "example: ", "</b>" "<p>this is a test</p>", "<p>", "p", "this is a test", "</p>"
254
Chapter 11
Command Reference
Regular Expressions
Active4D v5
version 3.0
Discussion This command puts a backslash in front of every character in inString that is part of the regular expression syntax. This is useful if you have a dynamically generated string that you need to match in some text and the string may contain special regex characters. If inDelimiter is specified, it will also be escaped. This is useful for escaping the delimiter that is used in your regex patterns, such as / . The special regular expression characters are:
. \ + * ? [ ^ ] $ ( ) { } = ! < > | : .
Example Lets say you are going to do a regex match on a string entered by the user in the form field f_find You would need to do something like this: .
selection to array([Contacts]Last; $lastNames) $pattern := "/" + regex quote pattern(_form{"f_find"}; "/") + "/i" $index := regex find in array($lastNames; $pattern)
Chapter 11
Command Reference
255
Active4D v5
Regular Expressions
regex replace
regex replace(inPattern; inSubject; inReplacement; outResult {; inLimit}) Parameter inPattern inSubject inReplacement outResult inLimit Type Text | String/Text Array Text/BLOB | String/Text Array Text | String/Text Array Text/BLOB | String/Text Array Number Description Search pattern(s) Source text to search Replacement text Receives replaced text
Discussion This command searches inSubject for matches to inPattern and replaces them with inReplacement. If inLimit is specified, only inLimit matches will be replaced. If inLimit is omitted or is <= 0, all matches are replaced. If matches are found, the new subject(s) will be returned in outResult, otherwise the subject(s) will be returned unchanged. inSubject and outResult may be the same variable. If inSubject is a BLOB, then outResult must also be a BLOB, and they are both assumed to be in the format UTF8 Text without length. Every parameter to regex replace (except inLimit) can be an array. If inSubject is an array, the search and replace is performed on every element of inSubject, and outResult will be an array with the same number of elements. If inPattern and inReplacement are arrays, then regex replace walks through the arrays in parallel and uses the corresponding elements to do a search and replace on inSubject. If inReplacement has fewer elements than inPattern, an empty string is used for the remaining replacement values. If inPattern is an array and inReplacement is a string, regex replace searches inSubject for each pattern and replaces with the replacement string. If inPattern is a string and inReplacement is an array, it is an error, as this does not make sense. Replacement Syntax The real power in regex replace lies in the replacement syntax. In addition to referencing matched strings, you may also manipulate the case of the result. In the case of the \N notation, \0 returns the entire matched pattern, \1 returns the first captured subpattern, and so on. Thus \0 and & are equivalent.
256
Chapter 11
Command Reference
Regular Expressions
Active4D v5
Action Returns the Nth captured subpattern Returns the Nth captured subpattern Returns the named subpattern Returns the entired matched pattern Starts an uppercase run Starts a lowercase run Ends an uppercase or lowercase run Uppercases the next letter Lowercases the next letter
If you are using the \N notation and it is directly followed by a number, you must use the \{N} form to separate the pattern number from the number that follows. For example, if you want to replace a match with the first captured subpattern followed by the number 1, you must do it this way:
\{1}1
If your replacement pattern contains the character & and you do not intend it to be replaced with the entire matched pattern, it must be preceeded with a backslash. The \U and \L markers begin a case-changing run. Every character between these markers and either a \E marker or the end of the replacement has its case changed accordingly. Pattern and subpattern substitutions are done before case changes so you can change the case of matched patterns. For example, the replacement text:
\U&\E \L\1\E
would uppercase the entire matched pattern and lowercase the first captured subpattern. The \u and \l markers are similar, but they change the case of the next character only. So the replacement syntax:
\u& \l\1
would uppercase the first character of the entire matched pattern and lowercase the first character of the first matched subpattern. The /e Pattern Option If the search pattern included the /e option, after all replacements are done, the replacement text is executed as Active4D code and the result is used as the replacement text.
Chapter 11
Command Reference
257
Active4D v5
Regular Expressions
For example, this replacement text would return the first two characters of the entire matched pattern:
return (substring("\U&\E"; 1; 2))
If the entire matched pattern is John Doe this expression would first resolve to: ,
return (substring("JOHN DOE"; 1; 2))
Then this text would be executed, which would return JO as the replacement text. Note a few important things in this example:
3 You must use return to return the value to regex replace 3 When using a match pattern in an expression, be sure to enclose it in double quotes. 3 When you specify the replacement text, it is usually enclosed in double quotes, so you
must escape double quotes within the replacement text like this:
$replace := "return (substring(\"\U&\E\"; 1; 2))"
Because the replacement text is executed as Active4D code within the context of the current execution, you may do anything you wish, including:
3 Use any supported commands. 3 Call Active4D and 4D methods. 3 Access any local variables that were available within the scope of the regex replace
command.
3 Access any of the built-in collections such as form variables and query params. 3 Execute more than one line of code by separating the lines by \r as long as the last ,
line executes a return statement. Examples This example uses the /e pattern modifier to lowercase HTML tags in the subject:
$pattern := "/(<\/?)(\w+)([^>]*>)/e" $replace := "return (\"\1\" + lowercase(\"\2\") + \"\3\")" regex replace($pattern; "<EM>test</EM>"; $replace; $result) writebr($result; ""; A4D Encoding All) // Output is: <em>test</em>
258
Chapter 11
Command Reference
Regular Expressions
Active4D v5
This example replaces all occurrences of foo at the beginning of the subject with bar , and replaces all occurrences of bar at the end of the subject with foobar:
array text($patterns; 0) set array($patterns; "/^foo(\w*)/"; "/(\w*)bar$/") array text($subjects; 0) set array($subjects; "foo is bar"; "fool's gold"; \\ "raise the bar"; "rebar") array text($replacements; 0) set array($replacements; "bar"; "foobar") regex replace($patterns; $subjects; $replacements; $results) writebr(join array($results; "<br />\n")) // Output is: bar is foobar bar's gold raise the foobar foobar // using named subpatterns $pattern := "/(?P<area>\d{3})-?(?P<exch>\d{3})-?(?P<num>\d{4})/" $replace := "(\<area>) \<exch>-\<num>" regex replace($pattern; "5551234567"; $replace; $result) // $result = "(555) 123-4567"
regex split
version 3.0
regex split(inPattern; inSubject; outResults {; inLimit {; inFlags}}) Number Parameter inPattern inSubject outResults inLimit inFlags Result Type Text Text/BLOB String/Text Array Number Number Number Description Delimiter pattern Source text to split Receives split strings Limit on number of matches Controls behavior of split Number of split strings
Discussion This command is similar to the split string command, but inSubject is split along the boundaries matched by inPattern. If inLimit is specified, then only substrings up to inLimit are returned, and if inLimit is <= 0, it actually means no limit which is useful when you want to pass inFlags as well. , inFlags can be any combination of the following flags, which may be combined with bitwise | operator:
Chapter 11
Command Reference
259
Active4D v5
Regular Expressions
Flag A4D Regex Split No Empty A4D Regex Split Capture Delims
Effect Only non-empty pieces will be returned Parenthesized expressions in the delimiter pattern will be captured and returned
260
Chapter 11
Command Reference
Request Cookies
Active4D v5
Request Cookies
Active4D puts client cookies and their associated values into a collection. You can access this collection in your scripts. The values in the request cookies collection are all text. Note that no character set conversions or decoding is done on this text; it is considered opaque by Active4D. It is up to you to properly encode cookie values when you set them. The request cookies collection is read-only, and follows the same pattern as all read-only collections.
Chapter 11
Command Reference
261
Active4D v5
Request Cookies
request cookies
request cookies Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the request cookies collection. For more information on iterators, see Iterators on page 208.
version 2 modified v5
Discussion This command searches the request cookie collection for the item with the key inKey. If the item is found, the items value is returned. If the item is not found, an empty string is returned. Note: The cookie value is URL decoded and converted from UTF-8 to Unicode, so you do not need to perform any decoding.
262
Chapter 11
Command Reference
Request Cookies
Active4D v5
version 2 modified v5
Discussion This command fills outKeys and outValues with all of the keys and values in the request cookies collection. If outKeys was not defined, it is created as a string array. If outValues was not defined, it is created as a text array. If outKeys is defined but is not a string or text array, an error is generated an execution is aborted. Note: The cookie keys and values are URL decoded and converted from UTF-8 to Unicode, so you do not need to perform any decoding.
version 2
Discussion This command returns the number of items in the request infos collection.
Chapter 11
Command Reference
263
Active4D v5
Request Info
Request Info
Every time Active4D receives an HTTP request, a number of headers are passed as part of the request, such as the content length and user agent identifier. Some of this information is commonly used, such as cookies, and is placed in specialized collections for easy access. All of the headers are put in the request info collection, which is accessible from your scripts. For more information on HTTP headers, see RFC 2616 at http://www.w3.org/Protocols/. In addition to all of the HTTP headers, all of the information put into the request info array (see A4D Execute <type> request on page 62) is also put into the request info collection. The request info array elements appear in the request info collection as the following items: Key *host *host address *host port *http version *remote address *request method *secure *virtual host Value Hostname used in request without port As set in 4D As set in 4D, usually 80 for HTTP or 443 for SSL "1.0" or "1.1" As set in 4D "GET" or "POST" As set in 4D, should be 1 for secure, 0 if not Virtual host configured in VirtualHosts.ini
The request info collection is read-only, and follows the same pattern as all read-only collections. All of the values in the request info collection are text.
264
Chapter 11
Command Reference
Request Info
Active4D v5
request info
request info Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the request info collection. For more information on iterators, see Iterators on page 208.
version 2
Discussion This command searches the request info collection for the item with the key inKey. If the item is found, the items value is returned. If the item is not found, an empty string is returned.
version 2
Discussion This command fills outKeys and outValues with all of the keys and values in the request infos collection. If outKeys was not defined, it is created as a string array. If outValues was not defined, it is created as a text array.
Chapter 11
Command Reference
265
Active4D v5
Request Info
If outKeys is defined but is not a string or text array, an error is generated an execution is aborted.
version 2
Discussion This command returns the number of items in the request cookies collection.
266
Chapter 11
Command Reference
Request Value
Active4D v5
Request Value
Occasionally you may not know which collection a value is in or you dont care which collection it is in, you just know that it was part of the request. In such cases you can use this command.
Chapter 11
Command Reference
267
Active4D v5
Request Value
version 2
Discussion This command searches these collections in order: query params, form variables, request cookies, request info. If the item is found, the items value is returned. If the item is not found, an empty string is returned.
268
Chapter 11
Command Reference
Resources
Active4D v5
Resources
Active4D enhances the Get indexed string and STRING LIST TO ARRAY commands to allow you to work with other resource types (such as 4DK#) that are in STR# format..
Chapter 11
Command Reference
269
Active4D v5
Resources
Get indexed string({*; inResType; } inResID; inIndex) Text Parameter * inResType inResID inIndex Result Type * Text Number Number Text Description Indicates a resource type is passed Four-character resource type ID of resource Index of string to get Requested string
Discussion This command works just like the 4D version of the command, but it also allows you to retrieve strings from resources such as 4DK# which are in STR# format.
$s := get indexed string(*; "4DK*"; 10; 1) // $s now contains something like "January:1:L". // We want only the name. $s := slice string($s; ":")
270
Chapter 11
Command Reference
Resources
Active4D v5
Description Indicates a resource type is passed Four-character resource type ID of resource All strings in resource
Discussion This command works just like the 4D version of the command, but it also allows you to retrieve strings from resources such as 4DK# which are in STR# format.
array string(15; $list; 0) string list to array(*; "4DK*"; 10; $list) // $s now contains strings like "January:1:L". // We want only the name. for ($i; 1; size of array($list)) $list{$i} := slice string($list{$i}; ":") end for
Chapter 11
Command Reference
271
Active4D v5
Response Buffer
Response Buffer
When you want to return data to the client, you do so by appending text to the response buffer. This buffer becomes the body of the HTTP response. The commands in this section allow you to write text and graphics to the response buffer, to get information about the size of the response buffer, and to control the character set conversion and encoding performed on text written to the response buffer.
272
Chapter 11
Command Reference
Response Buffer
Active4D v5
buffer size
buffer size Longint Parameter Result Type Longint
version 2 deprecated v5
Discussion This command has been replaced by response buffer size and is no longer supported.
version 3.0
Discussion This command the current size of the response buffer in bytes.
clear buffer
clear buffer
version 2 deprecated v5
Discussion This command has been replaced by clear response buffer and is no longer supported.
version 3.0
Discussion This command completely clears the contents of the response buffer. Ordinarily you would have no need to use this command.
Chapter 11
Command Reference
273
Active4D v5
Response Buffer
Discussion This command returns the current contents of the response buffer in outBuffer. If get response buffer is used with a BLOB, the BLOB receives UTF-8 encoded text, as if you had executed TEXT TO BLOB(buffer; outBlob; UTF8 Text without length). Note: Because execution is immediately terminated when binary data is written to the response buffer (e.g. with write gif ), it is guaranteed that the result of this command will be text.
Discussion This command works the same as write blob but replaces the contents of the response buffer for text types instead of appending. If set response buffer is used with a BLOB, the BLOB is assumed to contain text stored in the format UTF8 Text without length. It is designed for use in post-processing the response in the On Execute End event handler. For example, you could use get response buffer to get the response, regex replace to process the buffer, and then set response buffer to use the processed buffer.
274
Chapter 11
Command Reference
Response Buffer
Active4D v5
save output
save output(outBuffer) Parameter outBuffer Type <variant>
version 3.0
Discussion This command sets outBuffer as the response buffer. All output that would normally end up going back to the browser (i.e. HTML and the output of the various write commands) will instead be appended to outBuffer. outBuffer must be either a variant value (such as a local variable or collection item) or an element of a string/text array. Calls to save output must be balanced with a call to end save output, and the balancing call to end save output must be within the same scope as the corresponding call to save output. You may nest calls to save output. This allows you to construct complex nested output, like this:
writebr("---> level 1") save output($buffer) writebr("---> level 2") save output($buffer) writebr("---> level 3") writebr("<--- level 3") end save output write($buffer) writebr("<--- level 2") end save output write($buffer) writebr("<--- level 1")
At each level, we save the output to $buffer, then write it once we have restored the buffer. Note: Output is not available in outBuffer until after end save output is executed.
Chapter 11
Command Reference
275
Active4D v5
Response Buffer
version 3.0
Discussion This command restores the output buffer that was current before the most recent call to save output and places the contents of the current output buffer into the target value specified in save output. For more information, see save output on page 275.
version 2 modified v5
Discussion This command determines what character set conversion, if any, Active4D applies to text written to the response buffer. This conversion is applied after output character set encoding. You may either pass one of the character set constants below or an IANA character set name. The output character set constants supported by Active4D are: Character Set UTF-8 Macintosh Roman Macintosh Roman Windows Latin ISO-8859-1 (Latin1) Constant A4D Charset UTF8 A4D Charset None A4D Charset Mac A4D Charset Win A4D Charset ISO Latin1
If you pass a name, it must be a valid IANA character set name. If the name is empty, it will default to mac If it is invalid an error will be generated and execution will abort. .
276
Chapter 11
Command Reference
Response Buffer
Active4D v5
For more information on the output charset, see Working with Character Sets on page 100. Note: For compatibility with previous versions, A4D Charset None is now effectively the same as A4D Charset Mac, because Unicode always has to be converted to a different encoding before being sent to the browser.
version 2 modified v5
Discussion This command returns the name of the current output character set, which determines the character set to convert to when the response buffer is sent to the browser. The name returned by this command is the internal, canonical name used by ICU, and thus may not be the same name you used either in Active4D.ini or with the set output charset command. For a complete list of charset names, see: http://demo.icu-project.org/icu-bin/convexp?s=IANA&s=ALL For more information on the output charset, see Working with Character Sets on page 100.
version 2
Discussion This command determines what HTML character encoding, if any, Active4D applies to text written to the response buffer. This encoding is applied before output character set conversion. The inEncoding parameter is a set of bit flags which specify the characters to encode. Each bit flag has a named constants defined. The constants (and their values) are:
Chapter 11
Command Reference
277
Active4D v5
Response Buffer
3 A4D Encoding None (0): No encoding is performed. You are responsible for manually
encoding reserved characters, either by using the equivalent character entities directly or by using the html encode command.
3 A4D Encoding Quotes (1) : Single and double quotes are encoded. 3 A4D Encoding Tags (2) : The characters < and > are encoded. 3 A4D Encoding Ampersand (4): The ampersand character (&) is encoded. 3 A4D Encoding Extended (8) : All characters with an ASCII value >= 127 (nonbreaking space and international characters) are encoded.
3 A4D Encoding HTML (8) : A synonym for A4D Encoding Extended. This is the default. 3 A4D Encoding All (65535) : All characters that have HTML character entities defined
are encoded. The default for Chinese and Japanese language systems is A4D Encoding None. The default for all other systems is A4D Encoding HTML, which encodes only non-breaking space and international characters. This allows you to use the write command to create HTML tags, while converting international characters. For example, the following statement:
<% write("<td>Quelle btise!</td><td> </td>") %>
You can change the default output encoding with the output encoding option in Active4D.ini. For more information on output encoding, see Output Encoding on page 102.
version 2
Discussion This command returns the current set of bit flags which determine which characters to encode when writing to the response buffer. For more information on output encoding, see Output Encoding on page 102.
278
Chapter 11
Command Reference
Response Buffer
Active4D v5
write
write(inValue {; inFormat {; inOutputEncoding}}) Parameter inValue inFormat inOutputEncoding Type <any> Text | Number Number
version 1 modified v5
Description Value to write to the response buffer Format to use when converting to text Character encoding of HTML special characters and
Discussion This command works like the String command, but after converting inValue to text it appends the converted text to the response buffer. This is the primary method of generating dynamic HTML within Active4D code. If you pass a Boolean value without a format, it will automatically output True or False , depending on the value passed in. If a BLOB is passed to the write command, it is assumed to be text. You can specify the text format within the BLOB by passing the relevant constant (such as UTF8 Text without length) in the inFormat parameter. If no format is passed, the text format is assumed to be UTF8 Text without length. If inOutputEncoding is passed, the text being written will be encoded according to the encoding style specified. This is a more convenient way of specifying a special encoding than bracketing a call to write with calls to set output encoding. You may pass * as a shortcut for A4D Encoding All. For more information on the value of this parameter, see set output encoding on page 277.
write blob
write blob(inBlob; inContentType {; * | inCharset}) Parameter inBlob inContentType * inCharset Type BLOB Text * Text
Description BLOB to write to the response buffer Type of inBlobs contents If passed, forces binary type Character set of BLOB text
Chapter 11
Command Reference
279
Active4D v5
Response Buffer
3 Completely replaces the contents of the response buffer with the contents of inBlob if *
is passed or if the content type does not begin with text/ .
3 Sets the content type of the response based on inContentType, which may be either a
MIME type or a file extension. If inContentType is a file extension (with or without leading dot), the corresponding MIME type is looked up from ExtensionMap.ini. In either case, if the MIME type is not recognized, an error is generated and execution is aborted.
3 Stops execution of the script if the MIME type is binary, i.e. if * is passed or if the type
does begin with text/ .
3 If inContentType begins with text/ it is assumed that the entire BLOB contains text ,
stored in the format Mac Text without length or UTF8 Text without length.
3 If inContentType begins with text/ and * is not passed, inCharset can be an IANA
character set name which indicates the charset of inBlobs text. If inCharset is not passed, it defaults to UTF-8. This command is designed to allow you to return binary data which you have created outside of Active4D. For example, you may create a JPEG thumbnail on the fly which you want to return as the response.
query([pictures];[pictures]name = $f_name) $blob := MyCreateThumbnail([pictures]pict) write blob($blob; "image/jpeg")
Previous to Active4D v5, write blob could also be used to write text greater than 32K in length.This is still possible in v5, but completely unnecessary, as string and text variables in v5 are capable of holding up to 2GB of text. Note: It is up to you to ensure that inContentType matches the actual content type of inBlob.
280
Chapter 11
Command Reference
Response Buffer
Active4D v5
writebr
writebr(inValue {; inFormat {; inOutputEncoding}}) Parameter inValue inFormat inOutputEncoding Type <any> Text | Number Number
version 1
Description Value to write to the response buffer Format to use when converting to text Character encoding of HTML special characters
Discussion This command is a convenience routine for writing a value followed by an HTML line break and a line ending for the current platform (CR on Mac, CRLF on Windows). It is exactly equivalent to the following code:
write($inValue + "<br />" + $lineEnding; $inFormat)
writeln
writeln(inValue {; inFormat {; inOutputEncoding}}) Parameter inValue inFormat inOutputEncoding Type <any> Text | Number Number
version 1
Description Value to write to the response buffer Format to use when converting to text Character encoding of HTML special characters
Discussion This command is a convenience routine for writing a value followed by a line ending for the current platform (CR on Mac, CRLF on Windows). It is exactly equivalent to the following code:
write($inValue + $lineEnding; $inFormat)
Chapter 11
Command Reference
281
Active4D v5
Response Buffer
writep
writep(inValue {; inFormat {; inOutputEncoding}}) Parameter inValue inFormat inOutputEncoding Type <any> Text | Number Number
version 1
Description Value to write to the response buffer Format to use when converting to text Character encoding of HTML special characters
Discussion This command is a convenience routine for writing a value followed by an HTML paragraph break and a line ending for the current platform (CR on Mac, CRLF on Windows). It is exactly equivalent to the following code:
write($inValue + "<p>" + $lineEnding; $inFormat)
Note: This command is not recommended, because it uses a form of HTML that is no longer compliant with current HTML standards.
write raw
write raw(inValue {; inFormat}) Parameter inValue inFormat Type <any> Text | Number
version 2
Description Value to write to the response buffer Format to use when converting to text
Discussion This command is equivalent to the write command, but it temporarily disables the current output encoding, thus the output encoding parameter is not available. For example, if the current output encoding is A4D Encoding All, using the command
write("<b>This is bold</b>")
would not work as expected, because the output encoding would convert the HTML tags into HTML character entities, resulting in the following output: This would appear in
<b>This is bold</b>
the browser as the literal string passed in, not as bold text as intended.
282
Chapter 11
Command Reference
Response Buffer
Active4D v5
One could get the current output encoding, temporarily turn it off, then restore it, but that would quickly become cumbersome. By simply replacing write with write raw in the statement above, this problem can be quickly and easily avoided.
=
=inExpression Parameter inExpression Type <any>
version 2
Discussion The = operator, followed by an expression, may be used at the beginning of the first line of an Active4D code block as a synonym for the write command. When used in this manner, the code block will exit after the first line of code executes. This is very handy when using small Active4D code blocks embedded in a bunch of HTML. For example:
It is now <%=current time%> on <%=current date%>
Note that like the write command, the = operator will automatically convert the expression to text; you do not have to explicitly use the string command where the write command would not require it.
Chapter 11
Command Reference
283
Active4D v5
Response Cookies
Response Cookies
Active4D allows you to send cookies to the client browser. A cookie is basically a name and associated value which is stored on the clients machine. Cookies allow you to retain persistent information about a user across requests and sessions. You send cookies to the client browser by adding them to the response cookies collection. This collection is read-write, and follows the same pattern as all read-write collections. All of the values in the response cookies collection are text and are considered opaque by Active4D. It is up to you to do any necessary URL encoding or character set conversion.
Cookie Fields
In addition to a name and a value, cookies can optionally have other attributes, including domain, path, and expires. The complete Netscape cookie specification can be found at: http://developer.netscape.com/docs/manuals/js/client/jsref/cookies.htm The only cookie attribute you will usually be concerned with is expires. If this attribute is not specified, a cookie expires when the browser is closed. To create a cookie that is retained across browser sessions, you must set the expires attribute to some date in the future. Active4D provides commands to do this.
response cookies
response cookies Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the response cookies collection. For more information on iterators, see Iterators on page 208.
284
Chapter 11
Command Reference
Response Cookies
Active4D v5
version 2 modified v5
Discussion This command searches the response cookie collection for the item with the name inName. If the item is found, the items value is returned. If the item is not found, an empty string is returned. Note: The cookie name and value are URL decoded and converted from UTF-8 to Unicode, so you do not need to perform any decoding.
version 2 modified v5
Discussion This command fills outNames and outValues with all of the names and values/attributes in the response cookies collection. Note that cookie attributes are stored along with the cookie value, as outlined in the Netscape cookie specification. If outNames was not defined, it is created as a Text array. If outValues was not defined, it is created as a Text array. If outNames is defined but is not a Text array, an error is generated an execution is aborted. Note: The cookie names and values are URL decoded and converted from UTF-8 to Unicode, so you do not need to perform any decoding.
Chapter 11
Command Reference
285
Active4D v5
Response Cookies
version 2 modified v5
Description Name of cookie to set Value to set Expiration date/time of cookie Cookie domain Cookie path
Discussion This command sets a response cookie with the given attributes. inValue may be of any type; it is converted to text automatically. Because cookies must have a non-empty value, if the value is an empty string, it defaults to null . If the cookie already exists, its value and attributes are reset to those given. If the item is not found, a new response cookie is added with the given name, value and attributes. If inExpires is a date, the cookie will expire at the current time on that date. If inExpires is text which is a properly formatted timestamp, the cookie will expire at the date and time given in the timestamp. If inPath is not given or is empty, it defaults to / . Note: Both inName and inValue are converted to UTF-8 and URL encoded, so you do not need to perform any encoding.
version 2
Discussion This command sets the expires date of the cookie with the name inName. You must create a cookie with set response cookie before using this command. If no cookie exists with the given name, an error is generated and execution is aborted.
286
Chapter 11
Command Reference
Response Cookies
Active4D v5
version 2
Discussion This command returns the current expires date of the cookie with the name inName. If no such cookie exists or the expires date has not been set, a null date is returned.
version 2
Discussion This command sets the domain of the cookie with the given name. You must create a cookie with set response cookie before using this command. If no cookie exists with the given name, an error is generated and execution is aborted.
version 2
Discussion This command returns the current domain of the cookie with the name inName. If no such cookie exists or the domain has not been set, an empty string is returned.
Chapter 11
Command Reference
287
Active4D v5
Response Cookies
version 2
Discussion This command sets the path of the cookie with the given name. You must create a cookie with set response cookie before using this command. If no cookie exists with the given name, an error is generated and execution is aborted.
version 2
Discussion This command returns the current path of the cookie with the name inName. If no such cookie exists or the path has not been set, an empty string is returned.
version 2
Discussion This command returns the number of items in the response cookies collection.
288
Chapter 11
Command Reference
Response Cookies
Active4D v5
version 2
Discussion This command searches the response cookies collection for the item with the name inName. To delete more than one item, you may use a wildcard in the name. All items that match will be removed from the collection, not from the client.
version 2
Discussion To delete a cookie from the client browser, you actually need to send a cookie with an expires date of !00/00/00!. This command is a convenience routine which does that for you. If you change the expires attribute to something other than !00/00/00! after calling this command, the cookie will not be deleted from the client browser. If the cookie to be abandoned was set with a domain and/or path, you must provide the same domain and/or path to successfully abandon it.
Chapter 11
Command Reference
289
Active4D v5
Response Headers
Response Headers
Active4D takes care of setting all of the response headers required by the HTTP protocol. In addition, it provides commands for setting various response properties that get turned into response headers (see Response Properties on page 294). If you need to set your own custom headers, you can do so by putting them in the response header collection. The response headers collection is read-write, and follows the same pattern as all readwrite collections. All of the values in the response headers collection are text and are considered opaque by Active4D. It is up to you to do any necessary URL encoding or character set conversion.
290
Chapter 11
Command Reference
Response Headers
Active4D v5
response headers
response headers Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the response headers collection. For more information on iterators, see Iterators on page 208.
version 2
Discussion This command searches the response header collection for the item with the name inName. If the item is found, the items value is returned. If the item is not found, an empty string is returned.
version 2
Discussion This command fills outNames and outValues with all of the names and values in the response headers collection. If outNames was not defined, it is created as a string array. If outValues was not defined, it is created as a text array.
Chapter 11
Command Reference
291
Active4D v5
Response Headers
If outNames is defined but is not a string or text array, an error is generated an execution is aborted.
version 2
Discussion This command searches the response headers collection for the item with the name inName. inValue may be of any type; it is converted to text automatically. If the item is found, its value is set to inValue. If the item is not found, a new item is added to the collection with the given name and value.
version 2
Discussion This command returns the number of items in the response headers collection.
292
Chapter 11
Command Reference
Response Headers
Active4D v5
version 2
Discussion This command searches the response headers collection for the item with the name inName. To delete more than one item, you may use a wildcard in the name. All items that match will be removed from the collection.
Chapter 11
Command Reference
293
Active4D v5
Response Properties
Response Properties
Most of the standard HTTP response headers generated by Active4D can be controlled through the commands in this group.
294
Chapter 11
Command Reference
Response Properties
Active4D v5
version 2
version 2
Discussion This command controls the cache-control response header. The default value for the cache-control response header is set by the cache control configuration option in Active4D.ini. The value of inOption should conform to the HTTP caching protocol as outlined in RFC 2616. Since HTTP 1.0 clients do not recognize the cache-control header, if inOption is nocache Active4D also sends a pragma: no-cache header and an expires header with a , time of now.
get expires
get expires Longint Parameter Result Type Longint Description Minutes till expiration
version 2
Discussion This command returns the minutes until the response should expire.
Chapter 11
Command Reference
295
Active4D v5
Response Properties
set expires
set expires(inMinutes) Parameter inMinutes Type Longint Description Minutes till expiration
version 2
Discussion This command controls the expires response header, which is used by HTTP clients to control caching of web pages. The default value for the expires response header is set by the expires configuration option in Active4D.ini. inMinutes is the number of minutes before the response should expire. A value of zero forces the response to expire immediately. A negative value will cause this value to be ignored by Active4D. Positive values are clipped to one year (in minutes).
version 2
Discussion This command returns the date and time at which the response should expire.
version 2
Discussion As an alternative to setting the number of minutes till expiration, you may also specify the exact date and time at which the response should expire. The date/time specified is clipped to one year from now.
296
Chapter 11
Command Reference
Response Properties
Active4D v5
version 2
Discussion This command returns the current MIME type of the response.
version 2
Discussion This command sets the Content-Type header of the response, which should be a valid MIME type. The default content type is text/html Ordinarily you would have no need to change . this, unless for example you are sending a plain text file, in which case you would set the content type to text/plain .
version 2 deprecated v5
Discussion This command is deprecated and is now an alias for the get output charset command.
Chapter 11
Command Reference
297
Active4D v5
Response Properties
version 2 deprecated v5
Discussion This command is deprecated and is now an alias for the set output charset command.
version 2
Discussion This command changes the status code that will be returned with the response. Named constants for the most common status codes can be found in Appendix B.
298
Chapter 11
Command Reference
Script Environment
Active4D v5
Script Environment
There are several configuration options that apply to Active4Ds scripting environment as a whole. Many of those options can be changed at runtime with the commands in this section. This section also contains utility commands for getting information about the host environment.
Chapter 11
Command Reference
299
Active4D v5
Script Environment
_request
_request Longint Parameter Result Type Longint
version 4.0
Discussion This command returns an iterator to a special built in collection which is automatically created with each executable request and then is automatically cleared at the end of the request. If you need to store data that is accessible globally, but only within a given request as opposed to the globals collection, which is global to all requests the _request collection is the perfect place to store that data.
version 4.0
Discussion This command returns everything after the hostname{:port} that was part of the requested URL.
current platform
current platform Number Parameter Result Type Number Description Current platform code
version 2
Discussion This command returns a number representing the platform under which Active4D is running. The number will either be 2 or 3, which can be tested with the named constants Power Macintosh and Windows respectively.
300
Chapter 11
Command Reference
Script Environment
Active4D v5
In case you hadnt noticed, this is a convenient replacement for the standard 4D incantation:
C_LONGINT($platform) PLATFORM PROPERTIES($platform) $0:=$platform
version 2
get license info(outUserName; outCompany; outLicenseType; outLicenseVersion; outServerIP; outExpirationDate; outPlatform {; outKeyFilePath}) Parameter outUserName outCompany outLicenseType outLicenseVersion outServerIP outExpirationDate outPlatform outKeyFilePath Type Text Text Longint Text Text Date Longint Text Description The licensed user The licensed company The type of license Active4D version licensed for IP address for a regular deployment license, empty otherwise Date a deployment license expires Always 3 (Mac and Windows) Full path to key file
Discussion This command returns license information from the key file of the machine on which Active4D is running. The license types are as follows: Type 0 1 2 3 4 5 License Trial Developer Deployment OEM Special Expired
If no key file is found, outLicenseType is 0 (Trial) and outExpirationDate is 00/00/00. If outLicenseType is 3 (OEM), outExpirationDate is 00/00/00. If outKeyFilePath is passed in, it receives the full URL path to the key file if it was found during startup.
Chapter 11
Command Reference
301
Active4D v5
Script Environment
version 2
Discussion This command returns the number of seconds remaining until the current license times out. If the license provides unlimited time, zero is returned. If the license has already timed out, -1 is returned.
get version
get version Text Parameter Result Type Text
version 1 modified v5
Discussion This command returns the following information about the instance of Active4D that is running: Item version architecture build type Values Active4D 5.XrXX Mac/Carbon, Mac/Mach-O, Win/x86 debug, release
For example, the 5.0r27 release version of Active4D running on Mac OS X would display the following version string:
Active4D 5.0r27 [Macintosh/Intel, release]
Note: The network layer, 4D host and build flags are no longer returned in v5. These values can now be found in the Active4D log file, along with complete 4D and system information.
302
Chapter 11
Command Reference
Script Environment
Active4D v5
parameter mode
parameter mode Text Parameter Result Type Text
version 2
Discussion This command returns the current setting of the parameter mode option in Active4D.ini, which will be either none form variables or query params , .
request query
request query Text Parameter Result Type Text Description Query string
version 4.0
Discussion This command returns the query string portion of the requested URL, if any (without the leading ?).
version 2 modified v5
Discussion This command sets the character set from which executable source files are converted to Unicode. You may either pass one of the character set constants below or an IANA character set name. The output character set constants supported by Active4D are: If you pass a name, it must be a valid IANA character set name. If the name is empty, it will default to mac If it is invalid an error will be generated and execution will abort. .
Chapter 11
Command Reference
303
Active4D v5
Script Environment
Character Set UTF-8 Macintosh Roman Windows Latin ISO-8859-1 (Latin1) Shift_JIS GB2312
Constant A4D Charset UTF8 A4D Charset Mac A4D Charset Win A4D Charset ISO Latin1 A4D Charset Shift_JIS A4D Charset GB2312
For more information on the platform charset, see Working with Character Sets on page 100.
version 2 modified v5
Description Name of the charset from which executable source files are converted
Discussion This command returns the current platform charset, which determines how Active4D converts executable source files to Unicode. The name returned by this command is the internal, canonical name used by ICU, and thus may not be the same name you used either in Active4D.ini or with the set platform charset command. For a complete list of charset names, see: http://demo.icu-project.org/icu-bin/convexp?s=IANA&s=ALL For more information on the platform charset, see Working with Character Sets on page 100.
304
Chapter 11
Command Reference
Script Environment
Active4D v5
version 2
Discussion You use the script timeout to ensure that an errant script doesnt go into an infinite loop and tie up server resources indefinitely. Active4D checks the timeout before executing each line of code. If the script has been running more than <script timeout> seconds, an error is generated and execution is aborted. This command sets the script timeout for the next execution of Active4D, not the one in which the command is used. In no case can the timeout be set lower than the script timeout setting in Active4D.ini.
version 2
version 2
Discussion You use the script timeout to ensure that an errant script doesnt go into an infinite loop and tie up server resources indefinitely. Active4D checks the timeout before executing each line of code. If the script has been running more than <script timeout> seconds, an error is generated and execution is aborted.
Chapter 11
Command Reference
305
Active4D v5
Script Environment
This command sets the script timeout only for the current execution of Active4D. In no case can the timeout be set lower than the script timeout setting in Active4D.ini or the most recent execution of the script timeout command.
version 2
Discussion This command returns the timeout of the currently executing script in seconds.
306
Chapter 11
Command Reference
Selecting Records
Active4D v5
Selecting Records
The commands in this section are enhanced versions of the standard 4D selection navigation commands. These commands are: ALL RECORDS FIRST RECORD LAST RECORD NEXT RECORD PREVIOUS RECORD GOTO RECORD GOTO SELECTED RECORD In addition to these commands, the SELECTION TO ARRAY and SELECTION RANGE TO ARRAY commands have been similarly enhanced. They are discussed in SELECTION/SELECTION RANGE TO ARRAY on page 146.
3 Globally: Active4D.ini has a pair of settings called auto relate one and auto relate
many These settings determine the default behavior for the commands listed above. . If you do not specify a value for these settings, the default is False. Setting them to True causes related one or related many records to be loaded whenever one of the commands above is executed, unless you override that behavior through one of the two techniques outlined below.
3 Per command: Each of the commands listed above adds two optional boolean
parameters, inRelateOne and inRelateMany. Specifying a value for these parameters overrides both the global default and the default for the currently executing script, if it was set by the auto relate command.
Chapter 11
Command Reference
307
Active4D v5
Selecting Records
Examples
Lets say you are looping through a selection of [ingredients] records and you want to display [vendor]name, which is related by a many to one relation from the [ingredients]vendor_id field to the [vendors]id field. Heres how you would ordinarily do it in Active4D:
for ($i; 1; records in selection([ingredients])) goto selected record([ingredients]; $i) relate one([ingredients]) writebr([ingredients]name + " comes from " + [vendors]name) end for
If the global auto relate one setting is not set or is set to False, and you do not use the auto relate command, and you do not use the optional flags in the GOTO SELECTED RECORD command, this is how you must do it. Now lets assume you want the convenience of always loading the related one records for all tables in your database. In that case you would change Active4D.ini:
auto relate one = true
By doing this, the code above could be written without using RELATE ONE:
for ($i; 1; records in selection([ingredients])) goto selected record([ingredients]; $i) writebr([ingredients]name + " comes from " + [vendors]name) end for
Then you realize that there are many tables for which you dont want to load the related one record, so you change the auto relate one setting in Active4D.ini to be False. This
308
Chapter 11
Command Reference
Selecting Records
Active4D v5
leaves you with two ways of loading the related [vendor] records without using RELATE ONE:
auto relate(true; false) // From this point on auto-load related one for ($i; 1; records in selection([ingredients])) goto selected record([ingredients]; $i) writebr([ingredients]name + " comes from " + [vendors]name) end for
for ($i; 1; Records in selection([ingredients])) // passing extra argument goto selected record([ingredients]; $i; true) writebr([ingredients]name + " comes from " + [vendors]name) end for
As you can see, there are many different ways to accomplish what you want. It is all a matter of how much control vs. convenience you want. Heres one thing to watch out for:
auto relate(true) query([ingredients]; [ingredients]name = "b@") // First record is loaded but no auto relate happens while(not(end selection([ingredients]))) writebr([ingredients]name + " comes from " + [vendors]name) end while
In this example, the first record in the selection resulting from the query would not have the related one record from [vendors] loaded, because no selection navigation commands were executed. To make this work correctly you would have to do this:
auto relate(true) query([ingredients]; [ingredients]name = "b@") first record([ingredients])
Chapter 11
Command Reference
309
Active4D v5
Selecting Records
auto relate
auto relate(inRelateOne {; inRelateMany}) Parameter inRelateOne inRelateMany Type Boolean Boolean
version 3.0
Description Sets auto-load of related one records Sets auto-load of related many records
Discussion This command sets the auto-loading of related one and related many records for the currently executing script. The settings specified here will override whatever the auto relate one and auto relate many settings are in Active4D.ini. The settings in this command will in turn be overridden by the extra parameters passed to the selection navigation commands as outlined below. For a complete discussion of auto-loading of related records, see Configuring Related Record Auto-loading on page 307.
Description Table on which to act Auto-load related one records Auto-load related many records
Discussion These commands act on the current record of inTable exactly as they do in 4D. In addition, if inRelateOne and/or inRelateMany are passed, they do the following:
3 inRelateOne: After the current record in inTable has been changed, if this parameter
evaluates to True, the related one record is loaded for each many to one relation in inTable. The relations must be automatic for this to work. If this parameter evaluates to False, the related one records will not be loaded. If this parameter is not passed, the behavior is specified by the auto relate command or the auto relate one setting in Active4D.ini.
310
Chapter 11
Command Reference
Selecting Records
Active4D v5
3 inRelateMany: The same as inRelateOne, but this controls the loading of related many records. If not passed the default behavior is specified by the auto relate command or the auto relate many setting in Active4D.ini.
version 3.0
Discussion This command gets the current state of auto-loading of related one and related many records for the currently executing script. For a complete discussion of auto-loading of related records, see the command auto relate on page 310 and Configuring Related Record Auto-loading on page 307.
GOTO RECORD
Discussion This command acts on the current selection and current record of inTable exactly as it does in 4D. In addition, the inRelateOne and inRelateMany parameters act as they do in the FIRST RECORD command, as described above.
Chapter 11
Command Reference
311
Active4D v5
Selecting Records
GOTO SELECTED RECORD([inTable]; inOffset {; inRelateOne {; inRelateMany}}) Parameter inTable inOffset inRelateOne inRelateMany Type Table Number Boolean Boolean Description Table on which to act Offset within selection to make current Auto-load related one records Auto-load related many records
Discussion This command acts on the current record of inTable exactly as it does in 4D. In addition, the inRelateOne and inRelateMany parameters act as they do in the FIRST RECORD command, as described above.
312
Chapter 11
Command Reference
Sessions
Active4D v5
Sessions
In 4D, between the time you start a process and the time the process dies, you can maintain the state of the process by using process variables. The HTTP protocol, on the other hand, is completely stateless. Between the time a client requests one page and another, the HTTP protocol provides no way of maintaining persistent state information about the client. Client-side cookies are one way of storing persistent information, but they are cumbersome and inefficient for storing much more than a few pieces of information. Thus the need arises for providing a persistent state mechanism. The solution which is widely accepted by web scripting environments is called a session. A session is a read-write collection which is maintained on the server and can be used to store and retrieve any number of values pertaining to a clients state, much as you would use process variables. Active4D transparently does all the work of creating and maintaining sessions. If you have never programmed for the web before, you will quickly discover that good session support is worth its weight in gold. If you have already programmed for the web, you know that good session support is very difficult meaning very expensive to implement. If you ask anyone who has ever tried to implement session support themselves, they will tell you that Active4Ds session support alone makes it worth the price!
Session ID
When a client visits your web site, Active4D looks for a cookie called ACTIVE4D_SESSIONID If the cookie is not there, Active4D assumes this is the first time . the client has visited your site since they launched their browser. Active4D then generates a new internal session ID and public session ID. Since you only work with the public session ID, it is simply called the session ID. Internal and public session IDs have the following characteristics:
3 Internal session IDs are 32-bit unsigned longints. 3 Public session IDs are 16-character strings. 3 Each time 4D is started, a random internal session ID starting value is selected. 3 For each Active4D session that is created, the internal session ID is incremented.
Chapter 11
Command Reference
313
Active4D v5
Sessions
3 The 32-bit internal session ID is mixed with random data and encrypted to generate a
16-character cookie string.
Session Events
When Active4D generates a new session ID, it checks to see if an On Session Start event handler has been defined in the Active4D library. If such an event handler is defined, it is executed. When the session is deleted, Active4D executes the On Session End event handler if one exists. For more information on event handlers, see Chapter 10, Event Handlers.
3 The On Session Start event handler is defined (it need not set any session data) 3 A script sets some session data 3 A script uses the session command to get a session iterator
If one of these conditions is not met, the next time that client browser accesses the server, a new session ID will be generated because there will be no ACTIVE4D_SESSIONID cookie. On the other hand, if the On Session Start event handler is defined or a session item is set, Active4D will send a cookie called ACTIVE4D_SESSIONID back to the client. The cookies value is the 16-character session ID. Each subsequent request by that browser until the client restarts the browser will include the ACTIVE4D_SESSIONID cookie with the session ID. Active4D decrypts the session ID into the internal session ID and restores the corresponding session collection. All of the data stored in the session during previous requests is then available to the current script. The session cookie sent by Active4D does not have an expiration. Cookies with no expiration are deleted when the browser closes, so a session is only valid as long as the originating browser remains open. Note: Active4D uses session cookies by default. You may disable session cookies (and session management as well) through the config options in Active4D.ini. For more information, see Session Configuration on page 316.
314
Chapter 11
Command Reference
Sessions
Active4D v5
Session Lifetime
Active4D maintains a clients session data for the lifetime of the session. The lifetime of a session is defined by two factors:
3 Your scripts may specifically use the abandon session command to expire a session.
Typically you would do this when a client logs out of your system.
3 If you do not specifically abandon the session, the sessions lifetime is defined by its
timeout, which is the maximum amount of time between requests that a session will stay alive. A session is still valid in code that is executed within the request in which it is abandoned or expires. In subsequent requests the sessions id is no longer valid. An abandoned or expired session is not immediately deleted from memory. Its time remaining is set to zero so that it will be deleted in the next cycle of the session purger. A background process periodically checks all sessions to see if they have timed out and purges those that have. The On Session End event handler is called for each session that is about to be purged. Within the context of that handler, the about-to-be-purged session is current and you can access all of its data. By default the timeout for a session is 10 minutes. This means that if a user logs in to your site, does some operations, and then leaves your site without logging out, their session will remain in memory for an additional 10 minutes before being deleted by the session purger.
Cookieless Sessions
If you decide to forego cookies as a means of storing the session ID, it is your responsibility to ensure that the session ID is always passed from one page to another, either through a hidden form field or through a query string parameter. If you fail to do so, you will lose track of the session. Active4D automatically creates a local variable which contains the session ID. The name of this variable is sid by default; you can change it with the session var name option in Active4D.ini. If Active4D is configured to use session cookies and it cannot find the cookie, or if it is configured not to use cookies, it automatically looks for the session variable either in the query params or in the form variables and then retrieves the session ID from the contents of that variable. When you want to pass the session ID as a hidden field, use the hide session field command. To pass the session ID in a query string, use the session query command to get a properly formatted query parameter.
Chapter 11
Command Reference
315
Active4D v5
Sessions
Because of the amount of memory sessions use, you should use sessions judiciously in your application. You would not want to store huge numbers of items in a session, nor store huge amounts of text in a session item. If this is necessary, consider either caching sessions in the database or storing some info in the database and some in the session.
Session Configuration
Active4D lets you configure every aspect of session management through options in Active4D.ini. session cookie domain HTTP cookies have a domain associated with them. The browser uses the domain and path to determine whether to send a cookie to the server. You may set the default session domain with this option. Ordinarily you would have no need to do so. The default value for this option is to have no domain. session cookie name This option determines the name of the cookie which Active4D looks for to find a session ID when the user makes a request. It must contain only alphanumeric characters or underscores with no spaces. The default value for this option is ACTIVE4D_SESSIONID .
316
Chapter 11
Command Reference
Sessions
Active4D v5
session cookie path HTTP cookies have a virtual path associated with them. The browser uses the domain and path to determine whether to send a cookie to the server. You may set the default session path with this option. Ordinarily you would have no need to do so. The default value for this option is to have no path. session purge interval This option determines the minimum time in seconds between attempts to purge expired sessions. In actual fact the interval may be something greater, since Active4D waits for all requests to finish before purging. Valid values for this option are between 5 and 60 inclusive. The default value for this option is 10. session timeout The length of time in minutes that a session can live without any user interaction. Values less than 1 will be ignored. The session timeout can be changed at runtime with the set session timeout command. To set the timeout to a value less than one minute, use a fraction. For example, a value of 0.5 would be 30 seconds. The default value for this option is 10. session var name The name of the local variable to automatically set to the current session ID (with or without the leading $). It must contain only alphanumeric characters or underscores with no spaces. The default value for this option is sid . use session cookies This option determines whether Active4D should store session IDs in cookies or look for the session variable. Setting this option to true or yes will turn cookies on, false or no will turn them off. The default value for this option is true . use sessions This option is a global switch for session management. If you are using sessions for your application, specify true or yes If you do not need session management at all, specify . false or no . The default value for this option is true .
Chapter 11
Command Reference
317
Active4D v5
Sessions
session
session Longint Parameter Result Type Longint Description Iterator reference
version 2
Discussion This command returns an iterator to the first item in the current session. For more information on iterators, see Iterators on page 208.
session to blob
session to blob{(ioBlob)} BLOB | <none> Parameter ioBlob Result Type BLOB BLOB
Discussion This command serializes the data in the current session. If ioBlob is passed, the serialized data is appended to ioBlob and nothing is returned. If ioBlob is not passed, the serialized data is returned as a new BLOB. In either case, you can store the BLOB somewhere for later restoral via blob to session. For an example of how to serialize and deserialize a session with embedded collections, see collection to blob on page 152.
318
Chapter 11
Command Reference
Sessions
Active4D v5
blob to session
blob to session(inBLOB {; ioOffset}) Parameter inBLOB ioOffset Type BLOB Number
Description BLOB with serialized collection data Offset within BLOB to get data
Discussion This command sets the current session from the serialized collection data contained in inBLOB. If ioOffset is passed, the serialized data must begin at that byte offset within inBLOB. After the session is successfully deserialized, ioOffset will point to the first byte beyond the serialized data. If inBLOB was not created with session to blob, an error will be generated and execution will be aborted. Note that this command will run the On Session End event handler on the old session, but the On Session Start event handler will not be run for the restored session, since you dont want to initialize it. Depending on what you do in On Session Start, you may have to factor out some code into a separate method and then call that method both from On Session Start and after calling blob to session. For an example of how to serialize and deserialize a session with embedded collections, see collection to blob on page 152.
get session
get session(inKey {; inIndex}) <any> Parameter inKey inIndex Result Type Text Number <any>
version 2
Description Key of session item to retrieve Array element to retrieve Value of session item or ""
Discussion This command searches the current session for the item with the key inKey. If the item is found and inIndex is not specified, the items value is returned. If the item value is an array, an empty string is returned. If the item is found and an index is specified, the given array element is returned. If the index is out of range, an error is generated and execution is aborted.
Chapter 11
Command Reference
319
Active4D v5
Sessions
If the item is not found, an empty string is returned. Note: This command has been superceded by the simpler syntax: session{inKey} or session{inKey}{inIndex}
version 2
Discussion This command searches the current session for the item with the key inKey. If outArray is not an array, an error is generated and execution is aborted. If the item is found and its value is an array, outArray receives a copy. If outArray has not yet been defined, it is created with the same type as the source array. If the item is found and its value is not an array, an error is generated and execution is aborted. If the item is not found, outArray is resized to zero. If outArray has not yet been defined, it is created as a text array. Note: Because you can reference arrays directly with the syntax session{"key"}, you may apply any array commands directly to the array within the session. Thus there is no longer any need for this command. It is kept only for backward compatibility.
version 2
Discussion This command searches the current session for the item with the key inKey. If the item is found and its value is an array, the size of the array is returned.
320
Chapter 11
Command Reference
Sessions
Active4D v5
If the item is found and its value is not an array, an error is generated and execution is aborted. If the item is not found, zero is returned. Note: This command has been superceded by the simpler syntax: size of array(session{inKey})
version 2
If the item is not found, an empty iterator is returned. For information on empty iterators, see Iterating Over a Collection on page 98.
version 2
Discussion This command fills outKeys with all of the keys in the session. If outKeys has not yet been defined, it is created as a string array. If outKeys is defined but is not a string or text array, an error is generated an execution is aborted.
Chapter 11
Command Reference
321
Active4D v5
Sessions
set session
set session(inKey; inValue {; inKeyN; inValueN | inIndex}) Parameter inKey inValue inIndex Type Text <any> Longint
version 2
Description Key of session item to store Value to set for the given item Index of array element to set
Discussion This command searches the current session for the item with the key inKey. If the item is found and its value is not an array, you may pass more than one key/value pair to set multiple items at once. If the item is found and its value is an array, you may pass an index to set an element of the array. If the item is found and an index is not specified, the items value is replaced with inValue. If the item is found, its value is an array, and an index is specified, the given array element is set. If the index is out of range or the type of inValue is not assignment-compatible with the array, an error is generated and execution is aborted. If the item is not found and an index is not specified, a new item is added to the session with the given keys and values. If the item is not found and an index is specified, an error is generated and execution is aborted. Note: This command has been superceded by the simpler syntax: session{inKey} := inValue or session{inKey}{inIndex} := inValue Here is an example of set session using multiple items:
set session("name"; "Aparajita"; "age"; 40) // session now contains two items
322
Chapter 11
Command Reference
Sessions
Active4D v5
version 2
Description Key of session item to store Array to set for the given item
Discussion This command searches the current session for the item with the key inKey. If inArray is not an array, an error is generated and execution is aborted. If the item is found, its value is replaced with inArray. If the item is not found, a new item is added to the session with the given key and array. Note: Because you can reference arrays directly with the syntax session{"key"}, you may apply any array commands directly to the array within the session. Thus there is no longer any need for this command. It is kept only for backward compatibility.
session has
session has(inKey {; *}) Boolean Parameter inKey * Result Type Text * Boolean Description Key of session item to test Perform wildcard search True if key is in session
version 2
Discussion This command searches the current session for the item with the key inKey. If * is passed, inKey may contain 4D wildcard characters and they will be honored in the search. If the item is found, True is returned, otherwise False.
Chapter 11
Command Reference
323
Active4D v5
Sessions
Because a session value can be of any type, it is not sufficient to use session{item} and check for an empty string being returned. You should always use this command to test for the existence of a session item, as shown here:
if (session{"test"} # "") // The test above would break if the item "test" existed // and was a number end if // The correct way if (session has("test")) $test := session{"test"} else session{"test"} := "this is a test" end if
version 2
Discussion This command returns the number of items in the current session.
version 2
Discussion This command searches the current session for the item with the key inKey. To delete more than one item, you may use a wildcard in the key. All items that match will be removed from the session.
324
Chapter 11
Command Reference
Sessions
Active4D v5
abandon session
abandon session
version 2
Discussion This command marks the current session to be expired when the current script finishes executing. After this command is executed, any changes made to the session are effectively lost. An abandoned session is not removed from memory and the On Session End handler is not run until the next session purge cycle.
session id
session id Text Parameter Result Type Text
version 2
Discussion This command returns the 16-character encrypted public session ID, not the internal session ID.
session internal id
session internal id Longint Parameter Result Type Longint Description Internal session ID
version 2
Discussion Active4D never directly uses the internal session ID. This command is here primarily because the Active4D Session Monitor (see The Session Monitor on page 556) displays internal session IDs. By using this command you can identify which session is active for a given browser and then view it in the Session Monitor.
Chapter 11
Command Reference
325
Active4D v5
Sessions
session local
session local Text Parameter Result Type Text
version 2
Discussion This command returns the name of the session ID local variable set by the session var name option in Active4D.ini.
session query
session query Text Parameter Result Type Text
version 2
Discussion This command is a convenience routine that returns the equivalent of:
session local + "=" + session id
If you are using cookie-based sessions, you would ordinarily have no use for this command. But if you are not using cookie-based sessions, it is your responsibility to pass the session ID in every form and every link. This command makes it easy to generate the correct query string parameter when building your links.
326
Chapter 11
Command Reference
Sessions
Active4D v5
version 2
Discussion This command is a convenience routine that performs the equivalent of:
write("<input type="hidden" name=\"%1%\" id=\"%1%\" value=\"%2%\" />" % (session local; session id))
If you are using cookie-based sessions, you would ordinarily have no use for this command. But if you are not using cookie-based sessions, it is your responsibility to pass the session ID in every form and every link. This command makes it easy to generate the correct hidden field within a form. Note: Make sure this command is called inside a form, otherwise it will have no effect.
version 2
Discussion This command sets the timeout of the current session in minutes. You can pass a fraction to set the timeout to less than one minute. For example, a value of 0.5 means 30 seconds.
Chapter 11
Command Reference
327
Active4D v5
Sessions
version 2
Discussion This command returns the timeout of the current session in minutes.
version 3.0
Description Receives internal session IDs Receives session timeouts in minutes Receives seconds remaining till sessions timeout Receives the memory used by the sessions in bytes
Discussion This command retrieves information about all current sessions. You can use this information to create an interactive web-based monitor of all current sessions. The arrays need not have been declared before calling this command, as they will be created on the fly with the specified type. If the array does exist, its type will be changed to the specified type. Sessions which have expired but have not yet been purged will be returned with a remaining time of zero. Note: This command is used by the a4d.debug library method dump session stats. For more on this method, see dump session stats on page 407.
328
Chapter 11
Command Reference
Strings
Active4D v5
Strings
Many, many new and incredibly useful string utilities have been added in Active4D. Learn them and you will save enormous amounts of time. Many of the most important additions to string handling are not in the form of commands but in the form of enhancements to the language. These are covered in the Interpreter chapter .
URL Encoding/Decoding
Internet standards dictate that URLs passed to web servers contain only a certain subset of the US-ASCII character set. All other characters are to be encoded in the form %NN, where NN is the hexidecimal value of the character in the US-ASCII character set. Active4D automatically decodes the standard HTTP request elements such as header names, form variables, query string parameters, etc., and converts them from UTF-8 to Unicode. However, there are some request elements, such as cookie values, that are considered opaque and are not decoded. Active4D provides a set of commands that facilitate the encoding and decoding of such opaque data: url decode url decode path url decode query url encode url encode path url encode query The query commands differ from the path commands in that:
3 The path commands pass through more characters unencoded (such as /) and
convert spaces to and from %20.
3 The query commands encode everything but -_.~!*'() and convert spaces to and
from +. You should use the path commands on the path portion of a URL, and the query commands on the query string portion of a URL. When encoding, Unicode text is converted to UTF-8 and then encoded.
Chapter 11
Command Reference
329
Active4D v5
Strings
If the preceding paragraph made no sense to you, dont worry. It is unlikely you will ever have to understand what it means.
330
Chapter 11
Command Reference
Strings
Active4D v5
% (formatting operator)
<format> % (arg1 {; ... argN}) Text Parameter format arg1...N Operator result Type Text <any> Text Description Format string Format arguments Formatted text
Discussion This operator takes a format string and applies one or more arguments to it. The format string can be any mixture of literal text and formatting directives which indicate the format and type of the argument that it applies to. Note: A BLOB argument is treated as raw text stored as UTF8 Text without length. The full syntax of the format string is beyond the scope of this document. You can read its documentation here: http://www.boost.org/libs/format/doc/format.html#syntax Here is an example:
// $cart is a RowSet $i := 1 $format := "%1%. %2% $%3$4.2f" while ($cart->next) $item := $cart->getRow writebr($format % ($i++; $item{"desc"}; $item{"price"})) end while // 1. 2. 3. output Acme Jet-pack $123.45 Spacely sprocket $27.95 Cogswell cog $7.99
There are many, many online examples of how to use this type of formatting. Just enter printf examples or printf tutorial into your favorite search engine. Note: In general the %% operator should be preferred over % because it works directly with Unicode, whereas the % operator has to convert all arguments to UTF-8, perform the formatting, then convert the result back to Unicode.
Chapter 11
Command Reference
331
Active4D v5
Strings
%% (formatting operator)
<format> %% (arg0 {; ... argN}) Text Parameter format arg0...N Operator result Type Text <any> Text Description Format string Format arguments Formatted text
v5
Discussion This operator takes a format string and applies one or more arguments to it. The format string can be any mixture of literal text and formatting directives which indicate the format and type of the argument that it applies to. Note: A BLOB argument is treated as raw text stored as UTF8 Text without length. The full syntax of the format string is beyond the scope of this document. You can read its documentation here: http://icu-project.org/apiref/icu4c/classMessageFormat.html Active4D supports longints, doubles, strings, times, and dates as format values. Booleans are also supported, but they are converted to the number 1 or 0, which is useful with choice formats. Here is an example:
// $cart is a RowSet $i := 1 $format := "{0}. {1} ${2,number,###0.00}" while ($cart->next) $item := $cart->getRow writebr($format %% ($i++; $item{"desc"}; $item{"price"})) end while // 1. 2. 3. output Acme Jet-pack $123.45 Spacely sprocket $27.95 Cogswell cog $7.99
Note that with the %% operator, parameter numbers are zero-based. The format string command is the equivalent of the %% operator in command form. Note: In general the %% operator should be preferred over % because it works directly with Unicode, whereas the % operator has to convert all arguments to UTF-8, perform the formatting, then convert the result back to Unicode.
332
Chapter 11
Command Reference
Strings
Active4D v5
capitalize
capitalize(inText {; *}) Text Parameter inText * Result Type Text * Text Description Text to capitalize Affect first letter only Capitalized text
version 3.0
Discussion This command capitalizes the first letter of each word it finds in inText. Word boundaries are defined by punctuation, control characters and whitespace, excluding single quotes (they are treated as apostrophes) and underscores. If * is not passed in, letters after the first letter are lowercased. If * is passed in, they are skipped. This allows you to maintain capitalization of words like ID .
write(capitalize("THIS IS ALL CAPS")) // output is "This Is All Caps" write(capitalize("name, ID"; *)) // output is "Name, ID"
cell
cell(inValue) Text Parameter inValue Result Type <any> Text
version 3.0
Discussion Because some browsers (notably Navigator 4.x) do not properly draw cells if they have no contents, it is best to fill empty cells with non-breaking spaces. You can use the cell command to quickly and easily take care of this without having to check for empty contents yourself. This command attempts to convert inValue to text according to the rules used by the String command. If inValue can successfully be converted to text, the length of the resulting text is checked. If the length is zero, the command returns the HTML non-breaking space for the current output charset, suitable for placing in the cell of an HTML table.
Chapter 11
Command Reference
333
Active4D v5
Strings
Note: This command is not necessary in modern browsers. The same effect can be achieved at a global level by putting the following style declaration in your main style sheet: table: { border-collapse: collapse } td, th: { empty-cells: show }
compare strings
compare strings(inSource; inCompare) Longint Parameter inSource inCompare Result Type Text Text Longint
version 2
Description Text to compare with Text to compare against Relative result of comparison
Discussion This command performs a bitwise comparison of the bytes in two strings. If inSource is bitwise greater than inCompare, a positive number is returned. If inSource and inCompare are bitwise equal, zero is returned. If inSource is bitwise less than inCompare, a negative number is returned.
334
Chapter 11
Command Reference
Strings
Active4D v5
concat
concat(inDelimiter; inString1; inString2 {; ...inStringN}) Text Parameter inDelimiter inString1 inString2 Result Type Text Text Text Text
version 2
Description Text to put between strings First string Second string Concatenation of all strings
Discussion This command concatenates two or more strings together, placing inDelimiter between them. If a string is empty, no delimiter is inserted. This is basically a convenience routine that makes it easy to build full names, addresses, etc. without inserting extra spaces. For example:
writebr("[" + concat(" "; "John"; "J."; "Smith") + "]") writebr("[" + concat(" "; "John"; ""; "Smith") + "]") // output [John J. Smith] [John Smith]
Delete string
Delete string(inString; inFirstChar {; inNumChars}) Text Parameter inString inFirstChar inNumChars Result Type Text Number Number Text
Description String from which to delete Position of first character to delete Number of characters to delete Remaining string
Discussion The Active4D version of the Delete string command differs from 4Ds version in that you can pass a negative number for inFirstChar and inNumChars, which is converted to the index of the Nth Unicode code unit from the end of inString. When a negative number is passed for inNumChars, note that it signifies an index relative to the end of the string, not a number of characters relative to inFirstChar.
Chapter 11
Command Reference
335
Active4D v5
Strings
Examples
// Using negative number for inFirstChar $sub := Delete string("foobar.a4d"; -4; MAXTEXTLEN) // $sub = "foobar" // Using negative number for inNumChars // -2 means to delete through the 2nd to last char $sub := Delete string("12345"; 2; -2) // $sub = "15"
enclose
enclose(inValue {; inEnclosures}) Text Parameter inValue inEnclosures Result Type <any> Text Text
version 2
Discussion This command is a convenience for the common case when a value (usually a string) needs to be enclosed in some characters, such as double quotes. The command first attempts to convert inValue to text according to the default formatting for its type. If inValue is not of a type that can be converted to text , an error is generated and execution is aborted. If inEnclosures is not specified, the opening and closing enclosure characters default to double quotes (Char(34)). If inEnclosures is specified and is a single character, the opening enclosure character is set to that character. The closing enclosure character is set according to the following table: Opening enclosure ( [ { < Any other character Closing enclosure ) ] } > opening enclosure
If inEnclosures is specified and is more than one character, the opening enclosure character is set to the first character and the closing enclosure character is set to the second character. Some examples:
336
Chapter 11
Command Reference
Strings
Active4D v5
first not of
first not of(inSource; inMatchChars {; *}) Longint Parameter inSource inMatchChars * Result Type Text Text * Longint
version 2 modified v5
Description Text to search Characters to search for Perform a bitwise search Position of first matching character
Discussion This command searches inSource for the first character that does not match any of the characters in inMatchChars and returns its position. If no match is found, zero is returned. If * is not passed, the search is case and diacritical-insensitive (the backwards-compatible default). However, unlike the Position command, composed characters like will not be matched with non-composed equivalents like ss . If * is passed, the comparison is a strict bitwise comparison, which means case and diacriticals are significant.
Chapter 11
Command Reference
337
Active4D v5
Strings
first of
first of(inSource; inMatchChars {; *}) Longint Parameter inSource inMatchChars * Result Type Text Text * Longint
version 2 modified v5
Description Text to search Characters to search for Perform a bitwise search Position of first matching character
Discussion This command searches inSource for the first character that matches any of the characters in inMatchChars and returns its position. If no match is found, zero is returned. If * is not passed, the search is case and diacritical-insensitive (the backwards-compatible default). However, unlike the Position command, composed characters like will not be matched with non-composed equivalents like ss . If * is passed, the comparison is a strict bitwise comparison, which means case and diacriticals are significant.
format string
format string(inFormat; inArg0 {; ... argN}) Text Parameter inFormat inArg0..inArgN Result Type Text <any> Text Description Format string Format arguments Formatted text
v5
338
Chapter 11
Command Reference
Strings
Active4D v5
identical strings
identical strings(inString1; inString2) Boolean Parameter inString1 inString2 Result Type Text Text Boolean
version 2
Discussion This command does a strict case- and diacritical-sensitive comparison of the two strings and returns True if they are identical. This is very useful when comparing passwords.
Insert string
Insert string(inSource; inWhat; inWhere) Text Parameter inSource inWhat inWhere Result Type Text Text Number Text
v5 (enhanced 4D)
Description String in which to insert String to insert Position at which to insert New string
Discussion The Active4D version of the Insert string command differs from 4Ds version in that you can pass a negative number for inWhere, which is converted to the index of the Nth Unicode code unit from the end of inSource. For example, to insert 4 characters from the end of a string, you could use:
$s := insert string("foobar.a4d"; ".0"; -4) // $s = "foobar.0.a4d"
Chapter 11
Command Reference
339
Active4D v5
Strings
interpolate string
interpolate string(inString) Text Parameter inString Result Type Text Text Description Text to interpolate Interpolated text
version 4.0
Discussion This command interpolates inString according the rules for string interpolation as documented in String Interpolation on page 80. Ordinarily you dont need to use this command, because you can implicitly interpolate strings by using string literals with single-quotes. However, if you are dynamically building a string without string literals which you want to interpolate, you can use this command to do so.
last not of
last not of(inSource; inMatchChars {; *}) Longint Parameter inSource inMatchChars * Result Type Text Text * Longint
version 2 modified v5
Description Text to search Characters to search for Perform a bitwise search Position of first matching character
Discussion This command searches inSource for the last character that does not match any of the characters in inMatchChars and returns its position. If no match is found, zero is returned. If * is not passed, the search is case and diacritical-insensitive (the backwards-compatible default). However, unlike the Position command, composed characters like will not be matched with non-composed equivalents like ss . If * is passed, the comparison is a strict bitwise comparison, which means case and diacriticals are significant.
340
Chapter 11
Command Reference
Strings
Active4D v5
last of
last of(inSource; inMatchChars {; *}) Longint Parameter inSource inMatchChars * Result Type Text Text * Longint
version 2 modified v5
Description Text to search Characters to search for Perform a bitwise search Position of first matching character
Discussion This command searches inSource for the last character that matches any of the characters in inMatchChars and returns its position. If no match is found, zero is returned. If * is not passed, the search is case and diacritical-insensitive (the backwards-compatible default). However, unlike the Position command, composed characters like will not be matched with non-composed equivalents like ss . If * is passed, the comparison is a strict bitwise comparison, which means case and diacriticals are significant.
left trim
left trim(inString) Text Parameter inString Result Type Text Text Description Text to trim Trimmed text
version 2
Discussion This command trims control characters and whitespace from the beginning of inString and returns the result.
Chapter 11
Command Reference
341
Active4D v5
Strings
html encode
html encode(inString {; inMode}) Text Parameter inString inMode Result Type Text Longint Text Description Text to convert How to convert Converted text
v5
Discussion This command encodes HTML special characters (like "&") to ISO HTML character entities (like &), according to inMode and the current output charset. If inMode is not passed in, the conversion mode defaults to A4D Encoding HTML. If inMode is an asterisk, the conversion mode is A4D Encoding All. Otherwise you may pass a set of bit flags as you would to the set output encoding command. For more information on output encoding, see set output encoding on page 277. Note: html encode will only convert non-ASCII characters if the output charset is ISO-8859-1 or ISO-8859-15.
mac to html
mac to html(inString {; inMode}) Text Parameter inString inMode Result Type Text Longint Text Description Text to convert How to convert Converted text
version 1 deprecated v5
Discussion This command has been deprecated in favor of the renamed command html encode. It has been kept for backwards compatibility, but will be removed in a future version.
342
Chapter 11
Command Reference
Strings
Active4D v5
mac to utf8
mac to utf8(inText) Text Parameter inString Result Type Text Text Description Text Original text
Discussion As of v5, this command is deprecated and does nothing, since all text within Active4D is Unicode. It has been kept for backwards compatibility, but will be removed in a future version.
param text
version 2
param text({*; inDelimiters} inSource; inReplaceParam {; ...inReplaceParamN})Text Parameter * inDelimiters inSource inReplaceParam Result Type * Text Text <any> Text Description Indicates delimiters passed Delimiters for parsing inSource Text to parse Replacement parameter Transmogrified text
Discussion This little beauty is in actuality a powerful little string processor with an embedded language. At the simplest level, param text can be used to do multiple string replacements in one shot. All parameter placeholders indicated by ^N in the source text are replaced with the corresponding replacement parameters, where N is the relative number of the replacement parameter. Replacement parameters are automatically converted to text. For example:
// Current record of [Contacts] has Firstname="Buffalo", // Lastname="Bill" write(param text("Hello, ^1 ^2! How are you?"; \\ [Contacts]Firstname; \\ [Contacts]Lastname)) // output Hello Buffalo Bill! How are you?
Chapter 11
Command Reference
343
Active4D v5
Strings
In addition to simple parameter replacement, you can specify alternate subsections of the source string to be used depending on the value of the replacement parameters. Alternate subsections are marked in the form: <delim>N<delim>T1<delim>T2<delim> where <delim> is a delimiter character, N is a parameter number (one-based), T1 is the first choice, and T2 is the second choice. The delimiter characters are taken from the first two characters of inDelimiters. The default delimiters string is #| which is used if , inDelimiters is less than two characters. Three passes are made over the source string.
3 First the delimiter inDelimiters[[1]] is used, and if the value of parameter N evaluates to
zero, T1 is used, else T2 is used. A parameter is considered zero if it contains only numeric characters and converts to the number zero, or if its length = 0.
3 The second pass uses the delimiter inDelimiters[[2]], and if the value of parameter N
evaluates to 1, T1 is used, else T2 is used.
Multiply this by a hundred messages, and you can see why no one bothers to be grammatically correct with such messages. Using param text, you can easily handle such a situation like this:
$recs := records in selection([contacts]) $msg := "There |1|is|are| #1#no#^1# ^2|1||s| available." $msg := param text($msg; "#|"; $recs; "contact") // This code does the same as the case statement above.
344
Chapter 11
Command Reference
Strings
Active4D v5
Description literal text start a singular/non-singular selector use replacement parameter #1, $recs, as the selector insert is if $recs evaluates to 1, are otherwise start a zero/non-zero selector use replacement parameter #1, $recs, as the selector insert no if $recs evaluates to zero, replacement parameter #1 ($recs) if not insert replacement parameter #2, contact start a singular/non-singular selector use replacement parameter #1, $recs, as the selector do nothing if $recs evaluates to 1, insert s otherwise
It takes some getting used to, but once you master this mini-language you can eliminate a lot of code by programming your strings! Note: One useful technique is to use a boolean flag as a selector between alternate text. Simply pass a replacement parameter of String(Num($myBool)) and use a zero/non-zero selector.
Position
Discussion Active4D extends this 4D command by allowing you to do a reverse search. If inStart is not passed, it defaults to 1. If inStart is passed and is positive, the search starts at inSource[[inStart]]. If inStart is passed and is negative, the search starts inStart
Chapter 11
Command Reference
345
Active4D v5
Strings
characters from the end of inSource, so inStart of -1 would mean to start searching from the last character of inSource. If a reverse search is performed, inStart defaults to the end of inSource if it is not passed. Reverse searches begin at inSource[[inStart]] and proceed towards inSource[[1]]. Note that when searching in reverse, the start position marks the end of the portion of inSource that is searched. In other words, it is as if you are looking for the last occurrence of inFind within Substring(inSource; 1; inStart). outLengthFound and the final * have the same function as the last two parameters of the Position command in 4D.
Example
$source := "test123test" $pos := position("test"; $source) // forward search, $pos = 1 $pos := position("test"; $source; *) // reverse search from end, $pos = 8 $pos := position("test"; $source; 2) // forward search starting at 2nd char, $pos = 8 $pos := position("test"; $source; 7; *) // reverse search starting at 7th char, $pos = 1 $pos := position("test"; $source; -2) // forward search starting at 2nd char from end, $pos = 0 $pos := position("test"; $source; -1; *) // reverse search starting at 1st char from end, $pos = 8 $pos := position("test"; $source; -5; *) // reverse search starting at 5th char from end, $pos = 1
right trim
right trim(inString) Text Parameter inString Result Type Text Text Description Text to trim Trimmed text
version 2
Discussion This command trims control characters and whitespace from the end of inString and returns the result.
346
Chapter 11
Command Reference
Strings
Active4D v5
slice string
slice string(inString; inDelimiter {; outRemainder {; *}}) Text Parameter inString inDelimiter outRemainder * Result Type Text Text Text * Text Description Text to slice Where to slice Text after delimiter Bitwise matching Text before delimiter
Discussion This command slices a string into two parts that are separated by delimiter. If inDelimiter is found in inString, the text before the delimiter is returned. If outRemainder is passed, it is set to the text after the delimiter. If * is passed, delimiter matching is bitwise (case and diacritical sensitive). Otherwise the default (backward-compatible) behavior is to ignore case and diacriticals, and composed characters will be matched. For example, if the delimiter is ae the composed character , will be matched. If inDelimiter is not found, inString is returned whole and outRemainder is set to an empty string if it is passed.
Chapter 11
Command Reference
347
Active4D v5
Strings
split string
split string(inSource; inPattern; outArray {inPatternIsChars {; inCaseSensitive {; inLimit}}}) Longint Parameter inSource inPattern outArray inPatternIsChars inCaseSensitive inLimit Result Type Text Text String/Text Array Boolean Boolean Number Longint
version 2 modified v5
Description Text to split Provides splitting boundaries Receives chunks of inSource True if inPattern should be treated as an array of characters to match How to match inPattern Total number of splits that may be created Number of splits made
Discussion This command splits inSource into chunks and puts the chunks into outArray, according to the string inPattern. If inPatternIsChars is True (the default if not passed), the command splits the source string at any of the characters in inPattern. Pattern characters at the beginning and end of the source are stripped out, and empty elements are ignored. If inPatternIsChars is False, the command splits the source string at any occurrence of the entire pattern. Empty elements anywhere in the source are maintained. Case-sensitivity of pattern matching is set by inCaseSensitive. If not passed, matching is case sensitive by default. If inPatternIsChars is False and inCaseSensitive is False, split string will match composed characters. For example, if the pattern is ae the composed , character will be matched. inLimit limits the number of chunks that are created. Once the limit is reached, one more chunk is created with the rest of the string, whether or not it contains the pattern.
348
Chapter 11
Command Reference
Strings
Active4D v5
This command is especially useful for splitting formatted text such as tab-delimited strings.
$source := "This is a test" split string($source; " "; $chunks) // $chunks now contains 4 elements: "This", "is", "a", "test" split string($source; " "; $chunks; true; true; 2) // $chunks now contains 2 elements: "This", "is a test" split string("1||3|"; "|"; $params) // $params contains 2 elements: "1", "3" split string("1||3|"; "|"; $params) // $params contains 4 elements: "1", "", "3", ""
String
String(inValue {; inFormat}) Text Parameter inValue inFormat Result Type <any> Text | Number Text
Description Value to write to the response buffer Format to use when converting to text Converted value
Discussion The Active4D version of the String command differs from 4Ds version in that:
3 If you pass a Boolean value with a format, it will be converted to 1 or 0, which allows
you to use formats like Yes;;No .
3 If a BLOB is passed in, it is assumed to be text. You can specify the text format within
the BLOB by passing the relevant constant (such as UTF8 Text without length) in the inFormat parameter. If no format is passed, the text format is assumed to be UTF8 Text without length.
Chapter 11
Command Reference
349
Active4D v5
Strings
Substring
Subtring(inString; inFirstChar {; inNumChars}) Text Parameter inString inFirstChar inNumChars Result Type Text Number Number Text
Description String from which to get substring Position of first character of substring Size of substring Substring
Discussion The Active4D version of the Substring command differs from 4Ds version in that you can pass a negative number for inFirstChar and inNumChars, which is converted to the index of the Nth Unicode code unit from the end of inString. When a negative number is passed for inNumChars, note that it signifies an index relative to the end of the string, not a number of characters relative to inFirstChar. Examples
// Using negative number for inFirstChar $sub := substring("foobar.a4d"; -3) // $sub = "a4d" // Using negative number for inNumChars // -2 means to extract through the 2nd to last char $sub := substring("12345"; 2; -2) // $sub = "234"
trim
trim(inString) Text Parameter inString Result Type Text Text Description Text to trim Trimmed text
version 2
Discussion This command trims control characters and whitespace from the beginning and end of inString and returns the result.
350
Chapter 11
Command Reference
Strings
Active4D v5
url decode
url decode(inString) Text Parameter inString Result Type Text Text Description Text to decode Decoded text
version 2
version 2
Discussion This command decodes a URL-encoded string as a URL-encoded path. For more information on URL encoding and decoding, see URL Encoding/Decoding on page 329.
version 2
Discussion This command decodes a URL-encoded string as a URL-encoded query string. For more information on URL encoding and decoding, see URL Encoding/Decoding on page 329.
Chapter 11
Command Reference
351
Active4D v5
Strings
url encode
url encode(inString) Text Parameter inString Result Type Text Text Description Text to encode Encoded text
version 2
version 2
Discussion This command encodes inString into a URL-encoded path. For more information on URL encoding and decoding, see URL Encoding/Decoding on page 329.
version 2
Discussion This command encodes inString into a URL-encoded query parameter name or value. For more information on URL encoding and decoding, see URL Encoding/Decoding on page 329.
352
Chapter 11
Command Reference
Strings
Active4D v5
utf8 to mac
utf8 to mac(inString) Text Parameter inString Result Type Text Text Description Text to convert Converted text
Discussion This command is deprecated and does nothing, since all text is Unicode within Active4D. It has been kept for backward compatibility, but will be removed in a future version.
Chapter 11
Command Reference
353
Active4D v5
System Documents
System Documents
Active4D implements the most important document commands from 4D. In addition, it adds many new commands for manipulating files and directories and working with URLstyle paths.
Document Paths
As in 4D, a path passed to a document command may be full or partial, also known as absolute and relative. In addition, the path may be native or URL-style. If a path is native, it is considered a full path if it begins with a drive name and ends with either a directory name (for commands that take a directory) or a filename (for commands that take a filename). If the path is URL-style, it is considered a full path if it begins with /. If a path is native, it is considered a partial path if it does not begin with a drive name. If a path is URL-style, it is considered a partial path if it does not begin with /. A partial path is relative to the default directory (see The Default Directory on page 40). The last element of a full or partial path, whether a directory or filename, may be an alias (also known as a shortcut on Windows). Directories within a path may not be aliases.
3 For security reasons, all paths are checked to ensure they are either within the web
root directory or within one of the directories specified by the safe doc dirs option in Active4D.ini. Aliases are resolved prior to checking. If you want to use document commands on files outside of the root directory, you must add the directory path to the safe doc dirs path list in Active4D.ini. For information on Active4D.ini, see Chapter 3, Configuration.
3 You may pass a URL-style path (using / as the directory separator) instead of a native
path. If no / is in a path, it is assumed to be a native path.
3 To ensure proper functioning of your scripts, Active4D closes all documents that have
been opened with document commands when the script finishes executing. This prevents the situation where a script error leaves a file open and thus prevents other scripts from writing to the file.
Affected Commands
The document commands affected by the enhancements mentioned above are: The file upload command copy upload is also affected by these enhancements. See copy upload on page 191 for more information.
354
Chapter 11
Command Reference
System Documents
Active4D v5
Append document COPY DOCUMENT Create document DELETE DOCUMENT DELETE FOLDER DOCUMENT LIST
FOLDER LIST MOVE DOCUMENT Open document READ PICTURE FILE Test path name WRITE PICTURE FILE
Error Codes
All document-related commands set the Error variable to zero on success and an error code on failure. OK is set for commands that perform an operation and do not return an error code. If a document command returns an error number -70001 or lower, it is a standard C library error code and not a Macintosh error code. The actual C error code is:
abs(error) - 70000
So, for example, -70001 is 1, -70002 is 2, etc. C library error codes can be found here: http://www.finalcog.com/c-error-codes-include-errno
Chapter 11
Command Reference
355
Active4D v5
System Documents
Append document
Append document(inPath {; inType}) DocRef
Discussion The Active4D version of this command differs from the 4D version in that:
3 Passing an empty string for inPath will do nothing other than set OK to zero. 3 inType is ignored. The filename extension must be part of inPath.
Create document
Create document(inPath {; inType}) DocRef
Discussion The Active4D version of this command differs from the 4D version in that:
3 Passing an empty string for inPath will do nothing other than set OK to zero. 3 inType is ignored. The filename extension must be part of inPath.
current file
current file Text Parameter Result Type Text
version 2
Discussion This command returns the filename of the currently executing script. It is exactly equivalent to filename of(current path).
356
Chapter 11
Command Reference
System Documents
Active4D v5
current path
current path {({inWantLibraryPath}{*})} Text Parameter inWantLibraryPath * Result Type Boolean * Text
Description Return path to library Return web root-relative path Path of currently executing script
Discussion This command returns the path of the currently executing script in URL format. Unlike requested url, if this command is executed within an include file, the path of the include file is returned. If executed within a library, the path to the library is returned, unless inWantLibraryPath is passed and is False, in which case the path to the nearest script file in the source stack (if any) is returned. Note: If this command is executed within a library and inWantLibraryPath is not passed or is passed and is True, the * option is not supported. If executed within a text block, the path to the nearest script file in the source stack (if any) is returned. If the * is passed, the path returned is an absolute web root-relative path. Example Let us assume we are using the default web root, web whose path is the following (as , returned by get root: /HD/WebApps/MyApp/web/ If a script called act_mailReminder.a4d within the login directory within the web root executes current path. The result will be: /HD/WebApps/MyApp/web/login/act_mailReminder.a4d If the same script executes current path(*), the result will be: /login/act_mailReminder.a4d
Chapter 11
Command Reference
357
Active4D v5
System Documents
default directory
default directory{(*)} Text Parameter * Result Type * Text Description Use URL format for path Path to default directory
version 2
Discussion This command returns a full path to the default directory. For information on the default directory, see The Default Directory on page 40. If the * is not passed, a native path is returned with a native directory separator at the end. Passing * returns the path in URL format with / at the end.
DELETE FOLDER
DELETE FOLDER(inPath {; *}) Parameter inPath * Type Text *
version 2
Discussion If * is not passed, this command works exactly as its 4D counterpart does, in that only empty directories may be deleted. If * is passed, this command recursively deletes the directory and all of its contents. Warning: Using the DELETE FOLDER command in recursive mode is of course extremely dangerous. Be absolutely sure you know what you are deleting before using the recursive mode of this command.
358
Chapter 11
Command Reference
System Documents
Active4D v5
directory exists
directory exists(inPath) Boolean Parameter inPath Result Type Text Boolean
version 4.0
In other words, it will return True if the entity described by inPath exists and is a directory.
directory of
directory of(inPath {; *}) Text Parameter inPath * Result Type Text * Text
version 2
Description URL or native path Suppress trailing separator Directory portion of given path
Discussion This command returns the directory portion of the given path with a trailing directory separator, unless * is passed, in which case the trailing separator is suppressed. If inPath contains a forward slash (/), it is assumed to be a URL-style path.
directory separator
directory separator Text Parameter Result Type Text Description Native directory separator
version 2
Discussion This command returns the native directory separator for the currently running platform, which is : on Macintosh and \ on Windows.
Chapter 11
Command Reference
359
Active4D v5
System Documents
extension of
extension of(inPath) Text Parameter inPath Result Type Text Text
version 2
Discussion This command returns the filename extension, including the dot, of the given path. If the path ends in a directory, an empty string is returned.
file exists
file exists(inPath) Boolean Parameter inPath Result Type Text Boolean Description URL or native path True if is an existing file
version 4.0
In other words, it will return True if the entity described by inPath exists and is a file.
filename of
filename of(inPath {; *}) Text Parameter inPath * Result Type Text * Text
version 2 modified v5
Description URL or native path Strip extension Filename portion of given path
Discussion This command returns the filename portion of the given path. If inPath contains a forward slash (/), it is assumed to be a URL-style path.
360
Chapter 11
Command Reference
System Documents
Active4D v5
get root
get root({inVirtualHost}) Text Parameter inVirtualHost Result Type Text Text Description Virtual host name Full path of web root
version 1 modified v5
Discussion This command returns a full URL-style path to the web root directory, with a trailing /. If you have defined virtual hosts in VirtualHosts.ini and inVirtualHost is not passed, get root will return the mapped web root of the current virtual host. If inVirtualHost is passed and such a named virtual host exists in the virtual host table, the web root directory of that virtual host is returned. If no such named virtual host exists, the current web root directory is returned. This command is especially useful when building a path for use with the document commands, as in:
$path := join paths(get root; "templates/invoice.txt") $docRef := open document($path)
join paths
join paths({*; } inPathSegment1 {; inPathSegmentN}) Text Parameter * inPathSegmentN Result Type * Text Text
version 4.0
Discussion This command concatenates one or more path segments together intelligently. If any path segment is an absolute path, all previous segments are thrown away, and joining continues. The return value is the concatenation of the segments, with exactly one directory separator inserted between segments. If the optional * is not passed, the resulting path is in URL (Unix) format. If it is passed, the resulting path is in native format.
Chapter 11
Command Reference
361
Active4D v5
System Documents
This command is designed to relieve of the burden of checking whether or not directory path segments have a trailing directory separator, as in this example:
$docName := "2005-08-27.txt" open document(join paths(get root; "news"; $docName)) // result of join paths: /HD/Users/Homer/Documents/site/web/news/2005-08-27.txt
MOVE DOCUMENT
MOVE DOCUMENT(inSourePath; inDestPath {; *}) Parameter inSourcePath inDestPath * Type Text Text *
Discussion The Active4D version of this command differs from the 4D version in that:
3 If the optional * parameter is passed, the move is forced, even if a document exists at
the destination path.
version 2
Discussion This command converts a native path for URL-style path to a native path for the currently running platform.
362
Chapter 11
Command Reference
System Documents
Active4D v5
Open document
Open document(inPath {; inType {; inMode}}) DocRef
Discussion The Active4D version of this command differs from the 4D version in that:
3 Passing an empty string for inPath will do nothing other than set OK to zero. 3 inType is ignored. The filename extension must be part of inPath.
As of v5, the Open document command now conforms more closely to 4Ds behavior. In particular, an exclusive write lock is acquired on files opened in read/write or write mode. If no open mode is passed and a file is already open for writing, the file will be opened in read-only mode.
RECEIVE PACKET
Discussion This command differs from the 4D version in that it may only be used with documents, thus the document reference is required.
Chapter 11
Command Reference
363
Active4D v5
System Documents
requested url
requested url{(*)} Text Parameter * Result Type * Text
version 2
Discussion This command returns the path to the script that was requested in the current execution. If * is not passed, the root-relative virtual path (including /4DCGI) is returned. If * is passed, the full physical path to the requested script is returned in URL format.
writebr(requested url) writebr(requested url(*)) // virtual // physical
resolve path
resolve path(inPath {; *}) Text Parameter inPath * Result Type Text * Text Description Path to resolve Return native path Absolute path
v5
Discussion This command resolves relative paths, directory movement and aliases or shortcuts in inPath and returns an absolute full path. The path does not actually have to exist to be resolved. If * is not passed, the returned path is in URL (Posix) format. If * is passed, the returned path is in native 4D format (HFS on Mac OS X). If an error occurs while resolving the path, Error will contain an appropriate error code.
364
Chapter 11
Command Reference
System Documents
Active4D v5
SEND PACKET
SEND PACKET(inDocRef; inPacket)
Discussion This command differs from the 4D version in that it may only be used with documents, thus the document reference is required.
Discussion Named constants have been provided for the inAnchor: Position from start, Position from end, and Position from current.
split path
split path(inPath; outDirectory; outFilename {; *}) Text Parameter inPath outDirectory outFilename * Type Text Text Text * Description Path to split Directory portion of inPath Filename portion of inPath Suppress directory separator
v5
Discussion This command converts splits a path. outDirectory receives the directory portion of the path and outFilename receives the filename portion of the path. If inPath has no directory separators, outDirectory will be empty and outFilename will contain inPath. If inPath ends with a directory separator, outFilename will be empty. If * is not passed and inPath has more than one path component, outDirectory will have a trailing directory separator. If * is passed, the trailing directory separator in outDirectory is suppressed.
Chapter 11
Command Reference
365
Active4D v5
System Documents
version 2
Discussion This command converts a URL-style path to a native path for the currently running platform.
366
Chapter 11
Command Reference
Timestamps
Active4D v5
Timestamps
A common practice is database design is to define a timestamp field as part of each table. Timestamps are often used to mark creation date/time, modification date/time, etc.
Timestamp Format
A timestamp combines a date and time together into one Alpha field with a width of 17 characters. The format of a timestamp is as follows:
YYYYMMDDhhhmmssttt YYYY = 4-digit year MM = 2-digit month DD = 2-digit day hh = 2-digit hour (0-23) mm = 2-digit minute ss = 2-digit second ttt = 3-digit thousandths of a second (milliseconds)
By using this format, only one field can be used to store both the date and time. More importantly, a timestamp is formatted such that records can be sorted and compared by the timestamp, since the elements of the timestamp progress from most significant to least significant. Note: It is up to you to properly define the timestamp fields in your database.
Timestamp Time
To ensure consistency in timestamps, timestamps dates and times are converted from the local time zone to Coordinated Universal Time, also known as UTC or GMT. When working with timestamps, you always deal with the local time zone. All timestamp commands which create a timestamp expect a local date and time, and all timestamp commands that return a portion of the timestamp return a local date and/or time.
Timestamp Normalization
Timestamps are always kept in a normalized state the date and time always contain valid numbers. If a timestamp is created with a date or time where an element of the date or time is beyond the valid range for that element, the extra is factored into the next most significant element. If that element is then beyond the valid range, the process continues until all elements are normalized. For example, suppose you create a timestamp with the time 07:59:121. In this case, 121 seconds would be factored into the minutes, leaving us with two extra minutes and one second. The two extra minutes would then get factored into the hour, leaving us with one extra hour and one minute. So the normalized time would be 08:01:01.
Chapter 11
Command Reference
367
Active4D v5
Timestamps
Normalization allows you to do things like creating a timestamp which represents the 270th day of the year, like this:
$ts := timestamp(!01/270/01!) // $ts = "20010927050000000"
This is a situation you want to prevent, because User As changes will destroy the changes User B made changes which could very well be critical. In fact, once User B saves the changes, User As copy of the data is essentially incorrect. In a Client/Server database, you typically solve this problem by locking a record as soon as the user begins editing it. This is known as pessimistic locking, which leads to this scenario: 1 2 3 4 5 User A begins editing a record, locking that record to others. User B attempts to edit the same record, is told to wait until User A is finished. User A saves the changes and releases the lock. User B is allowed to edit the record. User B saves the changes to the record.
This technique is not without its problems. What if User A goes to lunch in the middle of editing the record? What if User B just wants to view the record without changing it? These problems can and have been solved in various ways, but the solutions are often cumbersome. Another approach which solves these problems is called optimistic locking. Heres how it works: 1 2 3 User A begins editing a record. The modification timestamp of the record is saved in the users session for later comparison. User B begins editing the same record. The modification timestamp of the record is saved in the users session for later comparison. User B attempts to save the changes to the record. Since the timestamp of the record matches the saved timestamp, the save is allowed and the timestamp is updated to the modification time. User A attempts saves the changes to the record. Because the saved timestamp does not match the records actual timestamp, the save is not allowed and the user is asked to try editing the record again.
368
Chapter 11
Command Reference
Timestamps
Active4D v5
This methodology is known as optimistic locking because it assumes that in the majority of cases there will not be a conflict which is indeed the case in the majority of applications. If you are writing a multiuser web application, you should definitely consider using timestamps and optimistic locking.
Chapter 11
Command Reference
369
Active4D v5
Timestamps
timestamp
timestamp Text timestamp(inDate {; inTime}) Text timestamp(inYear; inMonth; inDay; inHour; inMinute; inSecond; inMilliseconds) Text Parameter inDate inTime inYear inMonth inDay inHour inMinute inSeconds inMilliseconds Result Type Date Time Number Number Number Number Number Number Number Text Description Local date Local time Local year Local month Local day Local hour Local minute Seconds Milliseconds Timestamp
version 2
Discussion This command has three forms. The first form has no parameters and returns a timestamp for the current date and time. The second form takes a 4D date and time in the local time zone and creates a timestamp from those values. If inTime is not passed, it is assumed to be midnight in the local time zone (00:00:00). The third form specifies the exact values for each element of the timestamp. The values are in the local time zone. The result of each form is a 17-character string containing the given date and time, normalized to valid values and converted from the local time zone to UTC.
370
Chapter 11
Command Reference
Timestamps
Active4D v5
add to timestamp
add to timestamp(inTimestamp; inYears {; inMonths {; inDays {; inHours {; inMinutes {; inSeconds {; inMilliseconds}}}}}}) Text Parameter inYear inMonth inDay inHour inMinute inSeconds inMilliseconds Result Type Number Number Number Number Number Number Number Text Description Local year Local month Local day Local hour Local minute Seconds Milliseconds Timestamp
version 2
Discussion This command adds the specified number of date or time elements to inTimestamp and returns the result. Any of the values passed in may be negative. For example, to get a timestamp from 30 days ago, you would use this code:
$monthAgo := add to timestamp(timestamp; 0; 0; -30)
If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
timestamp difference
timestamp difference(inTimestamp1; inTimestamp2) Real Parameter inTimestamp1 inTimestamp2 Result Type Text Text Real Description A timestamp A timestamp Difference in seconds
version 4.0
Discussion This command subtracts inTimestamp2 from inTimestamp1 and returns the difference between them in seconds.
Chapter 11
Command Reference
371
Active4D v5
Timestamps
timestamp string
timestamp string(inTimestamp) Text Parameter inTimestamp Result Type Text Text Description A timestamp Formatted timestamp
version 2
Discussion This command formats inTimestamp as a local date and time in the form:
YYYY-MM-DD hh:mm:ss.ttt
To format a timestamp in another way, use the other timestamp commands to extract the timestamp elements and format them as necessary. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
timestamp date
timestamp date(inTimestamp) Date Parameter inTimestamp Result Type Text Date Description A timestamp Date of the timestamp
version 2
Discussion This command returns the date of the given timestamp, converted from UTC to the local time zone. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
372
Chapter 11
Command Reference
Timestamps
Active4D v5
timestamp time
timestamp time(inTimestamp) Time Parameter inTimestamp Result Type Text Time Description A timestamp Time of the timestamp
version 2
Discussion This command returns the time of the given timestamp, converted from UTC to the local time zone. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
version 2
Discussion This command returns the date and time of the given timestamp, converted from UTC to the local time zone. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
Chapter 11
Command Reference
373
Active4D v5
Timestamps
timestamp year
timestamp year(inTimestamp) Number Parameter inTimestamp Result Type Text Number Description A timestamp Year of the timestamp
version 2
Discussion This command returns the year of the given timestamp, converted from UTC to the local time zone. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
timestamp month
timestamp month(inTimestamp) Number Parameter inTimestamp Result Type Text Number Description A timestamp Month of the timestamp
version 2
Discussion This command returns the month of the given timestamp, converted from UTC to the local time zone. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
timestamp day
timestamp day(inTimestamp) Number Parameter inTimestamp Result Type Text Number Description A timestamp Day of the timestamp
version 2
Discussion This command returns the day of the month of the given timestamp, converted from UTC to the local time zone.
374
Chapter 11
Command Reference
Timestamps
Active4D v5
If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
timestamp hour
timestamp hour(inTimestamp) Number Parameter inTimestamp Result Type Text Number Description A timestamp Hour of the timestamp
version 2
Discussion This command returns the hour of the given timestamp, converted from UTC to the local time zone. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
timestamp minute
timestamp minute(inTimestamp) Number Parameter inTimestamp Result Type Text Number Description A timestamp Minute of the timestamp
version 2
Discussion This command returns the minute of the given timestamp, converted from UTC to the local time zone. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
Chapter 11
Command Reference
375
Active4D v5
Timestamps
timestamp second
timestamp second(inTimestamp) Number Parameter inTimestamp Result Type Text Number Description A timestamp Second of the timestamp
version 2
Discussion This command returns the second of the given timestamp. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
timestamp millisecond
timestamp millisecond(inTimestamp) Number Parameter inTimestamp Result Type Text Number
version 2
Discussion This command returns the millisecond of the given timestamp. If inTimestamp is not 17 characters, all of which are digits, an error is generated and execution is aborted.
376
Chapter 11
Command Reference
User Authentication
Active4D v5
User Authentication
User authentication requires a coordinated effort between the Realms.ini config file (which defines your security realms), the On Authenticate event handler (which must be defined to handle authentication), and the commands in this section. For information on Realms.ini, see Realms.ini on page 44. For information on the On Authenticate event handler, see On Authenticate on page 125.
Chapter 11
Command Reference
377
Active4D v5
User Authentication
auth password
auth password Text Parameter Result Type Text
version 2
Discussion This command returns the password of the authenticated user for the current realm, if any.
auth type
auth type Text Parameter Result Type Text
version 2
Discussion This command returns the type of authentication used. Currently the only authentication type supported is Basic .
auth user
auth user Text Parameter Result Type Text
version 2
Discussion This command returns the username of the authenticated user for the current realm, if any. If current realm returns a non-empty string and auth user returns an empty string, you know that the user has not yet been authenticated.
378
Chapter 11
Command Reference
User Authentication
Active4D v5
authenticate
authenticate{(inRealm)} Parameter inRealm Type Text Description Realm to pass to browser
version 2
Discussion This command generates the proper response status and headers to prompt a user authentication dialog on the client browser. If inRealm is not passed, the current realm as defined in Realms.ini is automatically passed to the client browser, otherwise inRealm is used. Browsers cache the username and password for a given realm until the browser is closed. This is a potential security risk if the user leaves a publicly accessible browser open. In addition, if the user logs out or is inactive for a long period without closing the browser, you may decide that the user must be reauthenticated. Some old browsers (most notably IE4) may not display an authentication dialog if passed a realm that has already been authenticated. You can force the browser to authenticate a user by changing the realm to some unique name, for example by appending the Tickcount. After the user enters his or her credentials, current realm will still return the original unadulterated realm name, since it is looked up in Realms.ini.
current realm
current realm Text Parameter Result Type Text Description Name of current realm
version 2
Discussion This command returns the name of the current realm, if any. The realm is determined by the Realms.ini config file.
Chapter 11
Command Reference
379
Active4D v5
Variables
Variables
Active4D provides a number of commands that extend what you can do with and to local variables in your scripts. Many of these commands were created for use with Active4Ds debugging tools.
380
Chapter 11
Command Reference
Variables
Active4D v5
defined
defined(inVariable | *; inVarName) Boolean Parameter inVariable * inVarName Result Type Variable * Text Boolean
Description Actual variable to test Check by name Name of variable to test True if defined in current scope
Discussion This command tests the existence of a variable. You may either pass a variable reference directly, or you may pass * followed by a variable name. Local variable names being tested should begin with $. This command tests whether or not a local variable has been assigned a value yet, and thus has been defined.
get local
get local(inName) <any> Parameter inName Result Type Text <any>
version 2
Discussion Given a local variable name (including the leading $), this command returns the variables value if it is both defined in the current scope and not an array, or an empty string if not.
Chapter 11
Command Reference
381
Active4D v5
Variables
local variables
local variables{(inScope)} Iterator Parameter inScope Result Type Text Iterator
Description Name of library.method for which to retrieve local variables Iterator to local variable collection
Discussion This command returns an iterator which you can use to iterate over the local variables in either the current scope, if inScope is not passed, or in a named scope, if inScope is passed. If inScope is passed, it must be in the form library.method, except for the top level scope, which must be called main . The keys of the collection referenced by the iterator are the variables names and the values are the variable values, which can be of any type.
set local
set local(inName; inValue) Parameter inName inValue Type Text <any>
version 2
Description Name of variable to set Value to set for the given variable
Discussion This command searches the local variables in the current scope for the variable with the name inName, which should include the leading $. If the variable is found and its value is not an array, the variables value is replaced with inValue. If the variable is found, and its value is an array, the current value of the array is set to inValue. If the variable is not found, a new variable is created with the given name and value.
382
Chapter 11
Command Reference
Variables
Active4D v5
type descriptor
type descriptor(inVariable) Text Parameter inVariable Result Type Variable Text
version 2
Discussion This command returns a textual description of the variables type, exactly as it would appear in the 4D debugger.
undefined
undefined(inVariable | *; inVarName) Boolean Parameter inVariable * inVarName Result Type Variable * Text Boolean
version 2
Description Actual variable to test Check by name Name of variable to test True if undefined in current scope
Chapter 11
Command Reference
383
Active4D v5
Variables
variable name
variable name(inVariable) Text Parameter inVariable Result Type Variable Text
version 2
Discussion Given an actual variable reference, this command returns the name of variable, or the name of the referent if passed a method reference parameter.
method "test"(&$inReferenceParam) $local := 13 writebr(variable name($local)) write(variable name($inReferenceParam)) end method $foo := 7 test($foo)
384
Chapter 11
Command Reference
Plugin Commands
Active4D v5
Plugin Commands
In addition to the execute plugin commands used to invoke Active4D, Active4D provides a number of utility plugin commands: A4D Base64 decode A4D Base64 encode A4D Blowfish decrypt A4D Blowfish encrypt A4D FLUSH LIBRARY A4D GET LICENSE INFO A4D Get root A4D GET SESSION DATA A4D GET SESSION STATS A4D Get time remaining A4D Get version A4D Import library A4D MD5 sum A4D Native to URL path A4D RESTART SERVER A4D SET ROOT A4D STRIP 4D TAGS A4D URL decode path A4D URL decode query A4D URL encode path A4D URL encode query A4D URL to native path
Chapter 11
Command Reference
385
Active4D v5
Plugin Commands
version 4.0
Discussion This command is the equivalent of the Active4D base64 decode command.
version 4.0
Discussion This command is the equivalent of the Active4D base64 encode command.
version 4.0
A4D Blowfish decrypt(inBlobData; inPassphrase {; inIV {; inCharset}}) Text Parameter inBlobData inPassphrase inIV inCharset Result Type BLOB Text Text Text Text Description Encrypted data Key used to encrypt data Seed text used to encrypt data Charset to convert from Decrypted text
Discussion This command is the equivalent of the Active4D command blowfish decrypt.
386
Chapter 11
Command Reference
Plugin Commands
Active4D v5
Description Text to encrypt Key used to encrypt text Seed text used for encryption Character set to convert to Encrypted data
Discussion This command is the equivalent of the Active4D command blowfish encrypt.
version 1 modified v5
Discussion This command purges the specified library from memory. The next import of the specified library will reload the library. If inLibName is * all libraries are flushed from memory. If inLibName @ all libraries , , except the Active4D library are flushed from memory. When you call A4D FLUSH LIBRARY, the library is not flushed immediately, because libraries cannot be flushed until all Active4D interpreters stop executing. Rather, a request to flush the given library is passed to the housekeeper process. The next time the housekeeper runs, it will wait for all interpreters to stop executing, then it will flush the library (or libraries). Because of this behavior, if A4D FLUSH LIBRARY is called again before the previous flush request is fulfilled, the second flush request will replace the first one. Ordinarily this should not be a problem, since you should not need to call A4D FLUSH LIBRARY at all. If inLibName is * or Active4D the Active4D library will be flushed and immediately , reloaded, but the On Application Start event handler will not be run again. You have to execute A4D RESTART SERVER to accomplish that.
Chapter 11
Command Reference
387
Active4D v5
Plugin Commands
In general, you should not flush the Active4D library. If you are developing the event handlers in the Active4D library, you should create an auxiliary library (e.g. _active4D.a4l) and pass the Active4D event handler calls to that library. When you modify the auxiliary library, it will be reloaded and the Active4D library will remain unaffected. Ordinarily you would have no need to use this command. If the auto refresh libs option is on in Active4D.ini, libraries are flushed and reloaded automatically when they are modified. If the auto refresh libs option is off, you must use this command to flush the library in order to reload it.
v5
Discussion This command returns the first IP address on the first ethernet interface on the host machine. The 4D Internet Commands plugin command IT_MyTCPAddr is currently broken, in that it returns IP addresses from non-ethernet interfaces like those created by VMWare.
v5
Discussion This command returns the MAC (Media Access Control) address of the first network interface on the host machine.
388
Chapter 11
Command Reference
Plugin Commands
Active4D v5
version 1
Discussion This command is the equivalent of the Active4D get root command.
version 2
Description Internal session ID to query Receives the item keys Receives the item types Receives the item values
Discussion This command retrieves information about all of the items in the session with the internal session ID inSessionID (as returned by the command session internal id). This command is used by the Active4D Session Monitor dialog. If the arrays are not of the correct type, OK is set to zero and the arrays are left untouched. If there is no current session or the session ID is invalid, the arrays are emptied and OK is set to zero. The value of an item is represented in textual form. Picture and BLOB items are returned as the size of the item in bytes. Arrays are returned as a CR-delimited list of items, as would be returned by the command join array($array; "\r"; 0; true; true).
Chapter 11
Command Reference
389
Active4D v5
Plugin Commands
version 2
Description Receives internal session IDs Receives session timeouts in minutes Receives seconds remaining till sessions timeout Receives the memory used by the sessions in bytes
Discussion This command retrieves information about all current sessions. This command is used by the Active4D Session Monitor dialog. If any of the arrays are not of the type specified, they are all sized to zero and OK is set to zero. If the command succeeds, OK is set to 1. Sessions which have expired but have not yet been purged (zombies) are returned with a remaining time of zero.
version 2
A4D GET LICENSE INFO(outUserName; outCompany; outLicenseType; outLicenseVersion; outServerIP; outExpirationDate; outPlatform {; outKeyFilePath}) Parameter outUserName outCompany outLicenseType outLicenseVersion outServerIP outExpirationDate outPlatform outKeyFilePath Type Text Text Longint Text Text Date Longint Text Description The licensed user The licensed company The type of license Active4D version licensed for IP address for a regular deployment license, empty otherwise Date a deployment license expires Always 3 (Mac and Windows) Full path to key file
Discussion This command is the equivalent of the Active4D command get license info.
390
Chapter 11
Command Reference
Plugin Commands
Active4D v5
version 4.5
Discussion This command returns the MAC address (ethernet ID) of the first network interface on the host machine.
version 2
Discussion This command is the equivalent of the Active4D command get time remaining.
version 1
Discussion This command returns a string describing the current version of Active4D.
Chapter 11
Command Reference
391
Active4D v5
Plugin Commands
version 2
Description The name of the library to import Contains any parsing errors that may occur HTTP status code
Discussion This command is the equivalent of the Active4D import command. If a parsing error occurs during the loading of the library, a status of 500 (Internal server error) will be returned, and outErrorMessage will contain information on the error. If the library loads successfully, a status of 200 (OK) will be returned and outErrorMessage will be empty.
A4D MD5
A4D MD5(inData {; inCharset}) Text Parameter inData inCharset Result Type Text Text Text
version 2
Discussion This command is the equivalent of the Active4D md5 sum command.
version 2
Discussion This command is the equivalent of the Active4D command native to url path.
392
Chapter 11
Command Reference
Plugin Commands
Active4D v5
version 2
Discussion This command restarts the Active4D HTTP server, flushing all libraries, abandoning all sessions, and reloading all configuration files.
v5
Discussion When called via On Web Connection, if Active4D receives a POST request, it calls a callback method to retrieve the body of the request. This command sets the method that Active4D calls. Note: The callback method must be in the host database, not in a component. If the callback method is found, 1 is returned. Otherwise zero is returned. The callback method should have the following code:
C_BLOB($0) GET HTTP BODY($0)
Chapter 11
Command Reference
393
Active4D v5
Plugin Commands
version 2
Discussion This command sets the web root directory. inPath may be an absolute or relative path in either native or URL (Unix) format. If it is a relative path, it is relative to the default 4D directory. For information on the default directory, see The Default Directory on page 40. The path may also use any of the directory tokens available to paths in Active4D.ini. For more information on the directory tokens, see Path Format on page 40. If inPath is a valid path, OK is set to 1. If it is not valid, OK is set to zero.
Discussion This command is deprecated and does nothing. It was only necessary with 4D 2003.
version 2
Discussion This command is the equivalent of the Active4D command url decode path.
394
Chapter 11
Command Reference
Plugin Commands
Active4D v5
version 2
Discussion This command is the equivalent of the Active4D command url decode query.
version 2
Discussion This command is the equivalent of the Active4D command url encode path, but it does not use the inUseAmpEntity parameter.
version 2
Discussion This command is the equivalent of the Active4D command url encode query.
Chapter 11
Command Reference
395
Active4D v5
Plugin Commands
version 2
Discussion This command is the equivalent of the Active4D command url to native path.
396
Chapter 11
Command Reference
CHAPTER 12 ..............................................................
Standard Libraries
Active4D extends its native command set by including a number of standard libraries that provide you which additional power and flexibility when creating your websites. The standard libraries may be placed in any Active4D folder in the library search path. Currently, the standard libraries are:
3 a4d.console 3 a4d.debug 3 a4d.json 3 a4d.lists 3 a4d.utils 3 a4d.web 3 Batch 3 Breadcrumbs 3 fusebox 3 fusebox.conf 3 fusebox.head 3 RowSet
Chapter 12
Standard Libraries
397
Active4D v5
a4d.console
a4d.console
This library is composed of methods that dump various data structures and internal information to the Active4D debug console. For more information on the debug console, see The Active4D Debugging Console on page 558. Ordinarily you will want to use the methods in a4d.debug to dump debugging information, as the formatting is considerably easier to read than what is output by the methods in a4d.console. However, there are times when you cannot dump information to a web page via the methods in a4d.debug. For example, there may be an execution error that is preventing the page from displaying. In such cases you can replace the method you would normally use in a4d.debug, such as dump collection, with the same method in a4d.console.
398
Chapter 12
Standard Libraries
a4d.console
Active4D v5
dump array
Discussion This method writes the contents of the given array to the debug console. The name of the array referred to by inArray and its type is displayed in the header. If inName is passed in, that is used instead of the source array name. If inDisplayInline is passed and is True, the current element of the array is displayed, followed by the elements of the array on one line, separated by commas. Otherwise the element number and element value are displayed in two columns. If the array is a String or Text array, the element values are surrounded by double quotes. If the array is a Longint or Real array and inDisplayCollections is passed and is True, array elements that are valid collection handles will be displayed as collections by calling dump collection.
dump collection
Discussion This method dumps the contens of the given collection to the debug console. The key and value of every item in the collection are displayed, and if inShowType is provided and is True, the value type is displayed after the key. If inName is passed, it is displayed in the header. If it is not passed, the name of the variable passed as inCollection is displayed in the header.
Chapter 12
Standard Libraries
399
Active4D v5
a4d.console
If an item value is an array, the display depends on the value of inInlineArrays. If inInlineArrays is not passed or is True, the current element of the array is displayed, followed by a comma-delimited list of the array elements, with text or string arrays having their elements surrounded by quotes. If inInlineArrays is False, arrays are displayed as if dump array($array; False; ""; True) is called. Warning: If an item of a collection is itself a collection reference, this method is called recursively to display its contents. So if you have any circular collection references infinite recursion and a crash will result.
version 4.0
Discussion This method calls the dump collection method, passing an iterator to the form variables collection.
version 4.5
Discussion This method creates a formatted dump of the relevant license information contained in your current key file, as well as the full path to the key file.
version 2
Discussion This method calls the dump collection method, passing an iterator to the query params collection.
400
Chapter 12
Standard Libraries
a4d.console
Active4D v5
version 2
Discussion This method calls the dump collection method, passing an iterator to the request info collection.
dump session
dump session
version 2
Discussion This method calls the dump collection method, passing an iterator to the current session.
Chapter 12
Standard Libraries
401
Active4D v5
a4d.debug
a4d.debug
This library is composed of methods that create a nicely formatted HTML dump of various data structures and internal information, suitable for viewing in a web page. Ordinarily you will want to use the methods in a4d.debug to dump debugging information, as the formatting is considerably easier to read than what is output by the methods in a4d.console. However, there are times when you cannot dump information to a web page via the methods in a4d.debug. For example, there may be an execution error that is preventing the page from displaying. In such cases you can replace the method you would normally use in a4d.debug, such as dump collection, with the same method in a4d.console.
402
Chapter 12
Standard Libraries
a4d.debug
Active4D v5
dump array
dump array(inArray {; inDisplayInline {; inName}}) Parameter inArray inDisplayInline inName Type Array Boolean Text
Description Array to dump If True, array is displayed on one line Name shown in header of dump
Discussion This method writes a formatted dump of the given array to the response buffer. The name of the array referred to by inArray and its type is displayed in the header. If inName is passed in, that is used instead of the source array name. If inDisplayInline is passed and is True, the current element of the array is displayed, followed by the elements of the array on one line, separated by commas. Otherwise the element number and element value are displayed in two columns; if the array is a String or Text array, the element values are surrounded by double quotes, and the length of the element is displayed in a third column. The current element number is hilited.
dump collection
dump collection(inCollection; { inName {; inShowType}}) Parameter inCollection inName inShowType Type Collection | Iterator Text Boolean
Description Iterator or handle of collection to dump Display name of collection True to display types of values
Discussion This method writes a formatted dump of the given collection to the response buffer. The key and value of every item in the collection are displayed in two columns, and if inShowType is provided and is True, a third column displays the value type. If inName is passed, it is displayed in the header. If it is not passed, the name of the variable passed as inCollection is displayed in the header.
Chapter 12
Standard Libraries
403
Active4D v5
a4d.debug
If the item value is an array, the current element of the array is displayed, followed by a comma-delimited list of the array elements is displayed, with text or string arrays having their elements surrounded by quotes. Warning: If an item of a collection is itself a collection reference, this method is called recursively to display its contents. So if you have any circular collection references infinite recursion and a crash will result.
version 2
Discussion This method calls the dump collection method, passing an iterator to the form variables collection. This is the preferred method of inspecting the form variables posted to a page.
Discussion This method creates a formatted dump of the relevant license information contained in your current key file, as well as the full path to the key file.
404
Chapter 12
Standard Libraries
a4d.debug
Active4D v5
dump locals
dump locals{(inShowChain {; inShowFusebox})} Parameter inShowChain inShowFusebox Type Boolean Boolean
version 3
Description Indicates all scopes should be dumped True to show the fusebox core and its variables
Discussion This command creates a formatted dump of the current local variables. If inShowChain is not passed or is False, dump locals only displays the local variables for the current scope. If inShowChain is passed and is True, all scopes in the call chain are dumped in succession, starting with the innermost scope and proceeding towards the top level scope. If inShowFusebox is not passed or is False, dump locals does not display the fusebox core and its variables. If inShowFusebox is passed and is True, all of the fusebox internals will be displayed. This command is especially useful for getting a quick snapshot of the local variable state at a given point in the script execution.
version 2
Discussion This method calls the dump collection method, passing an iterator to the query params collection. This is the preferred method of inspecting the query string in the request URL.
dump request
dump request
version 2
Discussion This method calls dump query params, dump form variables, dump request info, and dump session.
Chapter 12
Standard Libraries
405
Active4D v5
a4d.debug
version 2
Discussion This method calls the dump collection method, passing an iterator to the request info collection. This is the preferred method of inspecting the HTTP headers sent to a page.
dump selection
dump selection(inTable {; inFields}) Parameter inTable inFields Type Pointer Text
version 4.0
Discussion This method does a nicely formatted dump of the current selection of inTable. The current record within the selection is hilighted. If inFields is not passed, all fields in the table are displayed. If inFields is passed, it should be a semicolon delimited list of fields to display. Whitespace around the field name is ignored. If a field is in inTable, you do not need to specify the table name. You may also include fields from related one tables, in which case you must include the table name. You may also specify a format for a field by putting a format expression after the field name, separated by a colon. The format expression is what you would pass to the String command to format the fields value. For numeric types, use a format string (without quotes). For date and time fields, you may use a number or a 4D named constant such as HH MM SS . Note: Because semicolon is used as the field delimiter, you may not use semicolons in the field format. Examples The following code will display all fields for the [ingredients] table:
a4d.debug.dump selection(->[ingredients])
406
Chapter 12
Standard Libraries
a4d.debug
Active4D v5
The following code will display the id, name, and price fields from [ingredients], as well as the related one [vendors]name field. In addition, the price field will be formatted with the format string $###.00:
$fields := "id;name;price:$###.00;[vendors]name" a4d.debug.dump selection(->[ingredients]; $fields)
dump session
dump session
version 2
Discussion This method calls the dump collection method, passing an iterator to the current session. This is the preferred method of inspecting session values.
version 3
Discussion This method creates a formatted dump of all current sessions, displaying the following information, one row for each session: Column ID Timeout Time Remaining Size Description Session internal id Session timeout Time before session expires, zero means expired Total bytes of memory used by session
The rows may be sorted by passing in one of the column names in inSortBy. If no name or an invalid name is passed in, the rows will be sorted by the time remaining. The sort direction is determined by inDir. If inDir is not passed or is not valid, the rows will be sorted in ascending order.
Chapter 12
Standard Libraries
407
Active4D v5
a4d.debug
Sessions which have expired but have not yet been purged (zombies) will be displayed with a time remaining of 00:00:00 .
408
Chapter 12
Standard Libraries
a4d.json
Active4D v5
a4d.json
If you are using an AJAX-based Javascript library in your web sites (such as Ext, Prototype, jQuery or Dojo), at some point it is likely you will need to create JSON (see json.org) formatted data within Active4D. The a4d.json library makes is simple to create properly formatted JSON data, including convenience routines for quickly creating data from a selection of records or from a RowSet. Using the library The a4d.json library has two primary interfaces: a high-level interface and a low-level interface. Most of the time you will use the high-level interface to create, populate and output a JSON object Most of the high-level methods names begin with add If you . . need more control over the format of the JSON data, you can use the low-level methods, whose names begin with encode . UTF-8 and Ajax When using Ajax requests, posted data is encoded as UTF-8 and UTF-8 encoded data is expected in return. Active4D handles this transparently. When Active4D detects an Ajax request, it automatically decodes posted UTF-8 data into Unicode. If you use the a4d.json library to return data to an Ajax request, the data is automatically encoded as UTF-8.
Chapter 12
Standard Libraries
409
Active4D v5
a4d.json
new
new{(inWrap)} Object Parameter inWrap Result Type Boolean JSON Object
version 4.5
Description True to wrap the JSON data within an enclosing object JSON object to be used with other methods in this library
Discussion This method creates a new JSON object that can be used with other methods in this library to add JSON-formatted data. For information on objects created by Active4D libraries, see Creating a Poor Mans Class on page 120. If inWrap is not passed, it defaults to True. If inWrap is True, when a4d.json.toJSON/a4d.json.write is called the output will be wrapped within an enclosing object ({}).
add
add(self; inKey; inValue {; inFilter}) Object Parameter self inKey inValue inFilter Result Type JSON object Text <any> Text JSON object
version 4.5
Description Object to add data to Key for data item Data to add to JSON object Filter for collections self
Discussion This method adds data to a JSON object. If inKey is not an empty string, a new keyed item is added to the object. If inKey is empty, data is added without a key. Ordinarily you would only add data without a key if you are dynamically building an array using the startArray and endArray methods. The data in inValue is converted to JSON format according to its type: Value type String/Text Number Date Result Encoded string, double-quoted Number Date in IETF Mon Day, Year format
410
Chapter 12
Standard Libraries
a4d.json
Active4D v5
If inFilter is passed and inValue is a collection, it is used to filter the contents of inValue. For more information, see encodeCollection on page 427. Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Examples To understand how this method works, lets look at some examples to see the resulting output. First lets look at the output from the basic data types:
$json := a4d.json.new $json->add("name"; "Sri Chinmoy")->add("age"; 76) $json->add("birthdate"; !08/27/1931!)->add("Bengali"; true) $json->add("time"; ?07:13:27?) $json->write // The output is: {"name":"Sri Chinmoy","age":76,"birthdate":"Aug 27, 1931", "Bengali":true,"time":null}
Notice that the time item returned a value of null, because time is not a supported type in JSON. Also notice how we could chain multiple calls to add together. Note: If you are confused by the -> notation in the above example, see Creating a Poor Mans Class on page 120. Now lets look at what happens if we add a collection to a JSON object.
$json := a4d.json.new $json->add("name"; "Sri Chinmoy") $info := new collection("age"; 76; "birthdate"; !08/27/1931!; \\ "Bengali"; true; "time"; ?07:13:27?) array string(27; $info{"siblings"}; *; "Chitta"; "Mantu"; \\ "Hriday"; "Lily"; "Arpita"; "Ahana") $json->add("info"; $info) $json->write // The output is: {"name":"Sri Chinmoy","info":{"age":76,"birthdate":"Aug 27, 1931","Bengali":true,"time":null,"siblings":["Chitta","Mantu", "Hriday","Lily","Arpita","Ahana"]}}
Chapter 12
Standard Libraries
411
Active4D v5
a4d.json
As you can see, the items in a collection are added as a subobject with the given key. The values in a collection are added with the add method, unless a value is an array, in which case it is added using the addArray method. Next lets look at what happens if we add an existing JSON object to another JSON object.
$json := a4d.json.new $json->add("name"; "Sri Chinmoy") $info := a4d.json.new $info->add("age"; 76) $info->add("birthdate"; !08/27/1931!) $info->add("Bengali"; true) $info->add("time"; ?07:13:27?) $json->add("info"; $info) $json->write // The output is: {"name":"Sri Chinmoy","info":{"age":76,"birthdate":"Aug 27, 1931","Bengali":true,"time":null}}
412
Chapter 12
Standard Libraries
a4d.json
Active4D v5
addArray
addArray(self; inKey; inArray) Object Parameter self inKey inArray Result Type JSON object Text Array JSON Object
version 4.5
Description Object to add data to Key for data item Array to add to JSON object self
Discussion This method adds array data to a JSON object. If inKey is not an empty string, a new keyed item is added to the object. If inKey is empty, data is added without a key. Ordinarily you would only add data without a key if you are dynamically building an array using the startArray and endArray methods. The elements of inArray are converted to JSON format according to the array type: Value type ARRAY STRING/TEXT ARRAY INTEGER/LONGINT/REAL ARRAY DATE ARRAY BOOLEAN Result Encoded string, double-quoted Number Date in IETF Mon Day, Year format true or false
Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Note: For array types other than those listed above, this method will return an empty JSON array. Examples
array string(27; $names; *; "Tom"; "Dick"; "Harry") array longint($ages; *; 13; 27; 31) array picture($picts; 3) $json := a4d.json.new $json->addArray("names"; $names)->addArray("ages"; $ages) $json->addArray("oops"; $picts) $json->write // Output {"names":["Tom","Dick","Harry"],"ages":[13,27,31],"oops":[]}
Note that the picture array was encoded as an empty JSON array since pictures are not a supported data type.
Chapter 12
Standard Libraries
413
Active4D v5
a4d.json
addDateTime
addDateTime(self; inKey; inDate; inTime; inTimezone) Object Parameter self inKey inDate inTime inTimezone Result Type JSON object Text Date Time Number JSON Object
version 4.5
Description Object to add data to Key for data item Date portion of datetime to add to JSON object Time portion of datetime to add to JSON object Timezone portion of datetime to add to JSON object self
Discussion This method adds an IETF format datetime item to a JSON object. Such an item can be turned into a Javascript Date object by passing the item string to the Date constructor. If inKey is not an empty string, a new keyed item is added to the object. If inKey is empty, a datetime item is added without a key. Ordinarily you would only add a datetime without a key if you are dynamically building an array using the startArray and endArray methods. inTimezone should be in the timezone indicated in the inTimeZone parameter. inTimezone should be minute offset from GMT. Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Example
$json := a4d.json.new // add a datetime in EST (GMT-5) $json->addDateTime("DA"; !02/17/1980!; ?20:31:07?; -5 * 60) $json->write // The output is: {"DA":"Feb 17, 1980 20:31:07 GMT-0500"} // Javascript on the client, JSON is in a variable called json var da = new Date(json.DA)
414
Chapter 12
Standard Libraries
a4d.json
Active4D v5
addFunction
addFunction(self; inName; inBody) Object Parameter self inName inBody Result Type JSON object Text Text JSON Object Description Object to add data to Function name Function body self
version 4.5
Discussion This method adds an item to self with the key inName and a value of inBody as is, unquoted and unencoded. This is useful when you need to add a function (such as a handler or callback) to your JSON data. Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Example
$json := a4d.json.new $json->addFunction("renderer"; \\ """function(value, metadata, record) { return record.data.title + " " + value; }""")
addRowSet
addRowSet(self; inRowSet {; inCountKey {; inDataKey {; inMap {; inFirst {; inLimit}}}}}) Object Parameter self inRowSet inCountKey inDataKey inMap inFirst inLimit Result Type JSON object RowSet Text Text Text Number Number JSON Object
version 4.5
Description Object to add data to RowSet from which to get data Key for row count item Key for row data item JSON name to RowSet column map Index of first row to add Maximum number of rows to add self
Discussion This method adds rows from inRowSet to the JSON object self. If you have a RowSet and you want to use it for generating JSON data, this method is the fastest and easiest way to
Chapter 12
Standard Libraries
415
Active4D v5
a4d.json
do so. If the RowSet is selection-based and is not being used for other purposes, in most cases you will want to use addSelection instead of this method. The RowSets rows are added as an array of objects, with each object containing one item for each column of data. The column data is converted as if were passed to the add method. If inDataKey is passed and is non-empty, the array will have the key inDataKey. If inCountKey is passed and is non-empty, an item will be added to self whose key is inCountKey and whose value is the number of rows in inRowSet. Note: The number of rows returned with inCountKey is the result of calling $inRowSet->rowCount, not $inRowSet->sourceRowCount. If inMap is not passed or is empty, all of the columns in inRowSet will be added to the row array. If inMap is passed and is non-empty, it must be a semicolon-delimited list of mappings from RowSet column names to JSON key names. If the RowSet column name will be used as is, it is sufficient to use just the column name. If you want to rename a RowSet column, then the mapping should be a <JSON key>:<RowSet column> pair. This allows you to specify a subset of the RowSet columns for inclusion in the JSON data, and/or to rename the RowSet columns. If inFirst is passed and is >= 1, it specifies the one-based index of the first row from inRowSet that will be added to self. If inLimit is passed and is >= 0, it specifies the maximum number of rows from inRowSet that will be added to self. Together, inFirst and inLimit make it easy to specify a subset of rows, which is typically the case when paging through a large RowSet. Note: Depending on the Ajax toolkit you are using, it is likely that the start index for a page of data will be zero-based. It is up to you to add 1 to make it one-based before using the value for inFirst.
416
Chapter 12
Standard Libraries
a4d.json
Active4D v5
Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Examples Lets look at a few examples to illustrate the typical use of the various options. First, well create a RowSet and then add it a JSON object.
// Assume we have a selection of 3 [employee] records $map := """ name: concat(" "; [employee]first; [employee]last); id: [employee]id; birthdate: [employee]birthdate""" $rs := RowSet.newFromSelection(->[employee]; $map) $json := a4d.json.new $json->addRowSet($rs; "count"; "rows") $json->write // The output is: {"count":3,"rows":[{"name":"Tiny Tim","id":31,"birthdate":"Apr 12, 1932"},{"name":"James Taylor","id":27,"birthdate":"Mar 12, 1948"},{"name":"Pat Metheny","id":13,"birthdate":"Aug 12, 1954"}]}
Now lets add the rest of the parameters to see the effect. This time we want to eliminate the id column from the JSON data, and we want to rename the RowSet birthdate column to the JSON key dob. In addition, we are receiving the starting index in a query parameter called start whose value is 2 and the number of rows to return in a query parameter , called size whose value is 1 .
// RowSet setup is the same as the example above // Use "name" column as is, rename "birthdate" to "dob" $jmap := "name;dob:birthdate" // If "start" query param is not passed, default to "0", // convert it to one-based number $first := num($attributes{"start"} | "0") + 1 // If "size" query param is not passed, default to "20" $limit := num($attributes{"size"} | "20") $json := a4d.json.new $json->addRowSet($rs; "count"; "rows"; $jmap; $first; $limit) $json->write // The output is: {"count":3,"rows":[{"name":"Pat Metheny","dob":"Aug 12, 1954"}]}
Note that the count item still returns 3, because the number of rows in the RowSet is still 3, even though there is only one row in the rows array. The reason for this is because when you are showing paging information for a RowSet, you usually want to display something like Displaying records <start>-<end> of <total> so you always need the , total number of rows in the source dataset.
Chapter 12
Standard Libraries
417
Active4D v5
a4d.json
addSelection
addSelection(self; inTable {; inCountKey {; inDataKey {; inMap {; inFirst {; inLimit}}}}}) Object Parameter self inTable inCountKey inDataKey inMap inFirst inLimit Result Type JSON object Table pointer Text Text Collection Number Number JSON Object
version 4.5
Description Object to add data to Main table from which to get data Key for row count item Key for row data item JSON name to value map Index of first row to add Maximum number of rows to add self
Discussion This method adds record data from the current selection of inTable to the JSON object self. If you have a selection of records and you want to use it for generating JSON data, this method is the fastest and easiest way to do so. This method operates in two modes:
3 selection mode: If inFirst # -1, the selections records are output as an array of objects,
with each object containing one item for each field. inFirst specifies the one-based index of the first record in the current selection of inTable that will be added to self. If inLimit is passed and is >= 0, it specifies the maximum number of records from the current selection of inTable that will be added to self. Together, inFirst and inLimit make it easy to specify a subset of records, which is typically the case when paging through a large selection. Note: Depending on the Ajax toolkit you are using, it is likely that the start index for a page of data will be zero-based. It is up to you to add 1 to make it one-based before using the value for inFirst.
3 current record mode: If inFirst = -1, only the current record of the selection is output
as a single object (not within an array) with one item for each field. The field data is converted as if were passed to the add method. If inDataKey is passed and is non-empty, the record data will have the key inDataKey. If inCountKey is passed and is non-empty, an item will be added to self whose key is inCountKey and whose value is the number of records in the current selection of inTable. If inMap is not passed or is empty, all of the fields in inTable will be added to the record array, with the field name being the JSON column key. If inMap is passed and is non-zero, it must be a collection which maps JSON column keys to column values. The keys in inMap are used as the JSON column keys. The values may be one of three types:
418
Chapter 12
Standard Libraries
a4d.json
Active4D v5
3 Table pointer: If the value is a table pointer, the current record number for inTable is
output as a JSON number.
3 Field pointer: If the value is a field pointer, the value of the field is output as if it were
passed to the add method. Fields from tables other than inTable may be used if there is a many to one relation (it need not be automatic) between inTable and the foreign fields table. If any foreign fields are used in inMap, RELATE ONE($inTable->) is executed before each record is output to ensure related data is available.
3 Text: If the value is text, it must be an expression than returns a value (although using
return is not necessary). The resulting value is output as if it were passed to the add method. If you want to evaluate the expression in 4D instead of Active4D, prefix the expression with ! . If inMap contains an item whose key is a4d.json.callback then the value should be a text , block of code to execute after each record of inTable is loaded. The code does not have to return a value. If you want the code to be executed in 4D instead of Active4D, prefix it with ! Code executed in Active4D may consist of multiple statements separated by . carriage returns. Code executed in 4D may only be one line. Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Examples Lets look at a few examples to illustrate the typical use of the various options. First, well create a selection of records and then add it a JSON object.
// [employee] table // id Longint // firstname Alpha20 // lastname Alpha20 // company_id Longint, relate one with [company]id // dob Date query([employee]; [employee]contact_id = $attributes{"id"}) $json := a4d.json.new $json->addSelection(->[employee]; "count"; "rows") $json->write // The output is: {"count":3,"rows":[{"id":31,"firstname":"Tiny","lastname":"Tim", "company_id":101,"dob":"Apr 12, 1932"},{"id":27, "firstname":"James","lastname":"Taylor","company_id":107, "dob":"Mar 12, 1948"},{"id":13,"firstname":"Pat", "lastname":"Metheny","company_id":107,"dob":"Aug 12, 1954"}]}
Notice how all of the fields were automatically included in the JSON output. Now lets add the rest of the parameters to see the effect. To make the output more useful, we would like to do the following:
3 Include the record number of the [employee] table 3 Concatenate the first name and last name into a single name column 3 Return the company name instead of its id
Chapter 12
Standard Libraries
419
Active4D v5
a4d.json
// Selection setup is the same as the example above $map := new collection // output record number $map{"recnum"} := ->[employee] // output concatenation of firstname + " " + lastname $map{"name"} := "concat(\" \"; [employee]firstname; [employee]lastname)" // output foreign related one field $map{"company"} := ->[company]name // rename a field $map{"birthdate"} := ->[employee]dob // use a callback $map{"a4d.json.callback"} := \\ "query([family]; [family]employee_id = [employee]id)\r" + \\ "query([family]; &; [family]type = 1)" // type 1 is child $map{"num_children"} := "records in selection([family])" $json := a4d.json.new $json->addSelection(->[employee]; "count"; "rows"; $map) $json->write // The output is: {"count":3,"rows":[{"recnum":207,"name":"Tiny Tim", "company":"Tulips, Inc.","birthdate":"Apr 12, 1932", "num_children":0},{"recnum":331,"name":"James Taylor", "company":"Gorilla Corp.","birthdate":"Mar 12, 1948", "num_children":2}, {"recnum":713,"name":"Pat Metheny", "company":"The Way Up","birthdate":"Aug 12, 1954", "num_children":1}]}
420
Chapter 12
Standard Libraries
a4d.json
Active4D v5
startArray
startArray(self; inKey) Object Parameter self inKey Result Type JSON object Text JSON object Description Object to add data to Key for array item self
version 4.5
Discussion This method adds an array start marker to a JSON object. Ordinarily you would only call this method if you are dynamically building an array using the startArray and endArray methods instead of using the addArray method. Warning: To ensure valid JSON data, be sure to balance a call to this method with a call to endArray. If inKey is not an empty string, the array start marker is preceded by an item key.
Chapter 12
Standard Libraries
421
Active4D v5
a4d.json
Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Example
array string(27; $siblings; *; "Chitta"; "Mantu"; \\ "Hriday"; "Lily"; "Arpita"; "Ahana") $json := a4d.json.new $json->startArray("siblings") for each($siblings; $name) $json->add(""; $name) end for each $json->endArray $json->write // The output is: {"siblings":["Chitta","Mantu","Hriday", "Lily","Arpita","Ahana"]}
endArray
endArray(self ) Object Parameter self Result Type JSON object JSON object Description Object to add data to self
version 4.5
Discussion This method adds an array end marker to a JSON object. Ordinarily you would only call this method if you are dynamically building an array using the startArray and endArray methods instead of using the addArray method. Warning: To ensure valid JSON data, be sure to balance a call to this method with a previous call to startArray. Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Example See startArray on page 421.
422
Chapter 12
Standard Libraries
a4d.json
Active4D v5
startObject
startObject(self; inKey) Object Parameter self inKey Result Type JSON object Text JSON object Description Object to add data to Key for subobject self
version 4.5
Discussion This method adds an object start marker to a JSON object. Ordinarily you would only call this method if you are dynamically building an object using the startObject and endObject methods instead of using the add method. Warning: To ensure valid JSON data, be sure to balance a call to this method with a call to endObject. If inKey is not an empty string, the object start marker is preceded by an item key. Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Example
$json := a4d.json.new $json->startArray("employees") for each([employee]) $json->startObject $json->add("name"; [employee]name) $json->add("age"; [employee]age) $json->endObject end for each $json->endArray $json->write // The output is: {"employees":[{"name":"Tom","age":31},{"name":"Dick","age":27}, {"name":"Harry","age":42}]}
Chapter 12
Standard Libraries
423
Active4D v5
a4d.json
endObject
endArray(self ) Object Parameter self Result Type JSON object JSON object Description Object to add data to self
version 4.5
Discussion This method adds an object end marker to a JSON object. Ordinarily you would only call this method if you are dynamically building an object using the startObject and endObject methods instead of using the add method. Warning: To ensure valid JSON data, be sure to balance a call to this method with a previous call to startObject. Like all of the a4d.json methods, this method returns self, which allows you to chain several calls together on one line. Example See startObject on page 423.
toJSON
toJSON(self ) Text Parameter self Result Type JSON object Text
version 4.5
Discussion This method returns the data that has been added to self as JSON-formatted text. Usually you will not need to call this method directly, since you will want to write the reult of this method to the response buffer, and the a4d.json.write method does that for you. Warning: If you do decide to write JSON data to the response buffer yourself (instead of using a4d.json.write), be sure to use the write raw command to prevent any HTML encoding.
424
Chapter 12
Standard Libraries
a4d.json
Active4D v5
write
write(self; inSetContentType) Parameter self inSetContentType Type JSON object Boolean
version 4.5
Description Object from which to write JSON data True to set the content type
Discussion This method writes the data that has been added to self as JSON-formatted text to the response buffer. This is the primary method you will use to return JSON data to a client. If inSetContentType is not passed or is True, the content type of the response is set to application/json .
writep
writep(self ) Parameter self inCallback inSetContentType Type JSON object String Boolean
version 4.5
Description Object from which to write JSON data Callback expected by JSONP request True to set the content type
Discussion This method writes the data that has been added to self as JSON-formatted text to the response buffer, wrapped in a call to the function inCallback. This is the primary method you will use to return JSON data to a client that is using the JSONP protocol. If inSetContentType is not passed or is True, the content type of the response is set to application/json . Example Assume your front end makes a JSONP request with the following URL:
/enrollments/list?cb=CPJSONPConnectionCallbacks.callback32626
You build the JSON response and then return it like this:
$json := a4d.json.new // add data to $json $callback := $attributes{"cb"} $json->writep($callback)
// assuming fusebox
Chapter 12
Standard Libraries
425
Active4D v5
a4d.json
encode
encode(inValue {; inFilter}) Text Parameter inValue inFilter Result Type <any scalar value> Text Text Description Value to encode Filters collection items Encoded JSON data
version 4.5
Discussion This method encodes a scalar (non-array) value for use in a JSON object. Ordinarily you would have no need to call this method directly, as it is used internally by the various add methods. Depending on the type of inValue, one of the more specific encode<type> methods will be called.
encodeArray
encodeArray(inArray) Text Parameter inArray Result Type Array Text Description Array to encode Encoded JSON data
version 4.5
Discussion This method encodes the items in inArray as a JSON array for use in a JSON object. Each item in the array is encoded by calling the appropriate encoder for the array type. If the array type has no encoder, an empty array ([]) is returned. For a list of the supported array types, see addArray on page 413. Ordinarily you would have no need to call this method directly, as it is used internally by the various add methods.
426
Chapter 12
Standard Libraries
a4d.json
Active4D v5
encodeBoolean
encodeBoolean(inBool) Text Parameter inBool Result Type Boolean Text Description Value to encode Encoded JSON data
version 4.5
Discussion This method encodes a boolean value for use in a JSON object. Ordinarily you would have no need to call this method directly, as it is used internally by the various add methods. The value returned will be either true or false .
encodeCollection
encodeCollection(inCollection {; inFilter}) Text Parameter inCollection inFilter Result Type Collection Text Text Description Collection to encode Filters collection items Encoded JSON data
version 4.5
Discussion This method encodes the data in inCollection as a subobject for use in a JSON object. Each key of the collection is encoded by calling encodeString, and each value is encoded by calling the appropriate encoder for its type. If the type has no encoder, the value null is returned. Ordinarily you would have no need to call this method directly, as it is used internally by the various add methods. If inFilter is passed and is non-empty, it is used as a matching expression to determine which items from inCollection are encoded. The rules for the filter expression are as follows:
3 If the filter begins with "#", it performs an exclusion, i.e. all items that match the filter
are excluded.
3 Otherwise only items that match the filter are included. 3 If the first character after the optional # is "/", it is considered a regular expression
pattern and regex matching is done.
Chapter 12
Standard Libraries
427
Active4D v5
a4d.json
encodeDate
encodeDate(inDate) Text Parameter inDate Result Type Date Text Description Value to encode Encoded JSON data
version 4.5
Discussion This method encodes a date value for use in a JSON object. Ordinarily you would have no need to call this method directly, as it is used internally by the various add methods. The value returned will be in IETF Mon, Day Year format. For more information on date formatting, see add on page 410.
428
Chapter 12
Standard Libraries
a4d.json
Active4D v5
encodeString
encodeString(inString) Text Parameter InString Result Type Text Text Description Value to encode Encoded JSON data
version 4.5
Discussion This method encodes a string or text value for use in a JSON object. Ordinarily you would have no need to call this method directly, as it is used internally by the various add methods. The value returned is converted to UTF-8, surrounded with double quotes, and any nonprintable characters are encoded according to JSON rules.
Chapter 12
Standard Libraries
429
Active4D v5
a4d.lists
a4d.lists
Lists are a way of putting multiple values into a single string, delimited by some character. This is very handy for some types of problems. For example, a URL can be treated as a list of path elements delimited by "/". Or the string "one,two,three" can be treated as a list of three elements. Or you can encode a list of values in a list and store it in a database text field. Note the following attributes of lists:
3 Empty elements are ignored, so one,,three would be a list of two elements, one and
three .
3 Delimiters at the beginning and end of the list are ignored, so /one/two/three/
would be a list of three elements.
3 If the delimiter passed to a method contains more than one character, then any
character in the delimiter can delimit the list elements, but only the first character in the delimiter will be used if the method adds an element to the list.
3 List elements are numbered beginning at 1. 3 The default delimiter for all list methods is , .
430
Chapter 12
Standard Libraries
a4d.lists
Active4D v5
append
append(inList; inValue {; inDelim}) Text Parameter inList inValue inDelim Result Type Text <any> Text Text Description Delimited list Value to append List delimiter Modified list
version 3
Discussion This method appends a value to a list. The value can be of any type that can be converted to text with the String command (which includes String and Text). If inDelim is not passed, it defaults to , .
arrayToList
arrayToList(inArray {; inDelim}) Text Parameter inArray inDelim Result Type Array Text Text Description Array to convert List delimiter inArray as a delimited list
version 3
Discussion This method converts inArray into a delimited list. If inDelim is not passed, it defaults to , . Note: You can easily accomplish the same thing with the join array command.
Chapter 12
Standard Libraries
431
Active4D v5
a4d.lists
changeDelims
changeDelims(inList; inNewDelim {; inDelim}) Text Parameter inList inNewDelim inDelim Result Type Text Text Text Text Description Delimited list New delimiter to use List delimiter Modified list
version 3
Discussion This method changes the delimiters in a list and returns a modified copy. If inDelim is not passed, it defaults to , . Note: You can accomplish the same thing with replace string.
contains
contains(inList; inSubstr {; inDelim}) Boolean Parameter inList inSubstr inDelim Result Type Text Text Text Boolean
version 3
Description Delimited list Text to match List delimiter True if an element matches
Discussion This method returns True if any element in the list contains a substring, doing a case- and diacritical-sensitive match. If inDelim is not passed, it defaults to , .
432
Chapter 12
Standard Libraries
a4d.lists
Active4D v5
containsNoCase
containsNoCase(inList; inSubstr {; inDelim}) Boolean Parameter inList inSubstr inDelim Result Type Text Text Text Boolean
version 3
Description Delimited list Text to match List delimiter True if an element matches
Discussion This method returns True if any element in the list contains a substring, doing a case- and diacritical-insensitive match. If inDelim is not passed, it defaults to , .
deleteAt
deleteAt(inList; inIndex {; inDelim}) Text Parameter inList inIndex inDelim Result Type Text Number Text Text Description Delimited list Element to delete List delimiter Modified list
version 3
Discussion This method deletes an element from a list. If inDelim is not passed, it defaults to , .
find
find(inList; inMatch {; inDelim}) Number Parameter inList inMatch inDelim Result Type Text Text Text Number
version 3
Description Delimited list Text to match List delimiter Index of first matching element
Discussion This method returns the index of the first element of inList that exactly matches inMatch, doing a case- and diacritical-sensitive match. If no element matches, zero is returned.
Chapter 12
Standard Libraries
433
Active4D v5
a4d.lists
findNoCase
findNoCase(inList; inMatch {; inDelim}) Number Parameter inList inMatch inDelim Result Type Text Text Text Number
version 3
Description Delimited list Text to match List delimiter Index of first matching element
Discussion This method returns the index of the first element of inList that matches inMatch, doing a case- and diacritical-insensitive match. If no element matches, zero is returned. If inDelim is not passed, it defaults to , .
first
first(inList {; inDelim}) Text Parameter inList inDelim Result Type Text Text Text Description Delimited list List delimiter First element of list
version 3
Discussion This method returns the first element from a list, or an empty string if the list is empty. If inDelim is not passed, it defaults to , .
getAt
getAt(inList; inIndex {; inDelim}) Text Parameter inList inIndex inDelim Result Type Text Number Text Text Description Delimited list Element to get List delimiter Requested element of list
version 3
Discussion This method returns an indexed element from a list, or an empty string if the list is empty or inIndex is out of range.
434
Chapter 12
Standard Libraries
a4d.lists
Active4D v5
insertAt
insertAt(inList; inIndex; inValue {; inDelim}) Text Parameter inList inIndex inValue inDelim Result Type Text Number <any> Text Text Description Delimited list Where to insert Value to insert List delimiter Modified list
version 3
Discussion This method inserts an element into a list and returns a modified copy. The value can be of any type that can be converted to text with the String command (which includes String and Text). If inIndex < 1, the element is prepended. If inIndex > a4d.lists.len(inList), the element as appended. If inDelim is not passed, it defaults to , .
last
last(inList {; inDelim}) Text Parameter inList inDelim Result Type Text Text Text Description Delimited list List delimiter Last element of list
version 3
Discussion This method returns the last element from a list, or an empty string if the list is empty. If inDelim is not passed, it defaults to , .
Chapter 12
Standard Libraries
435
Active4D v5
a4d.lists
len
len(inList {; inDelim}) Number Parameter inList inDelim Result Type Text Text Number Description Delimited list List delimiter Number of elements in list
version 3
Discussion This method returns the number of element in a list. If inDelim is not passed, it defaults to , .
listToArray
listToArray(inList; outArray {; inDelim}) Parameter inList outArray inDelim Type Text Array Text Description Delimited list Array to set List delimiter
version 3
Discussion This method converts a delimited list into an array. If inDelim is not passed, it defaults to , . Note: You can accomplish the same thing with split string.
prepend
prepend(inList; inIndex; inValue {; inDelim}) Text Parameter inList inValue inDelim Result Type Text <any> Text Text Description Delimited list Value to insert List delimiter Modified list
version 3
Discussion This method inserts an element at the beginning of a list and returns a modified copy. The value can be of any type that can be converted to text with the String command (which includes String and Text). If inIndex < 1, the element is prepended. If inIndex > a4d.lists.len(inList), the element as appended.
436
Chapter 12
Standard Libraries
a4d.lists
Active4D v5
qualify
qualify(inList; inQualifier{; inDelim {; inCharAll}}) Text Parameter inList inQualifier inDelim inCharAll Result Type Text Text Text Text Text Description Delimited list String to enclose with List delimiter char or all New list
version 3
Discussion This method encloses the elements of inList with inQualifer (e.g. double quotes). If inCharAll is char the element will be skipped if it contains any digits. A modified copy , of the list is returned. If inDelim is not passed, it defaults to , .
rest
rest(inList {; inDelim}) Text Parameter inList inDelim Result Type Text Text Text Description Delimited list List delimiter New list
version 3
Discussion This method returns a copy of list starting from the second element. If inList has less than two elements, an empty string is returned. If inDelim is not passed, it defaults to , .
Chapter 12
Standard Libraries
437
Active4D v5
a4d.lists
setAt
setAt(inList; inIndex; inValue {; inDelim}) Text Parameter inList inIndex inValue inDelim Result Type Text Number <any> Text Text Description Delimited list Element to set Value to insert List delimiter Modified list
version 3
Discussion This method sets an element of a list and returns a modified copy. The value can be of any type that can be converted to text with the String command (which includes String and Text). If inIndex is out of range, nothing happens. If inDelim is not passed, it defaults to , .
sort
sort(inList {; inSortType {; inSortOrder {; inDelim}}}) Text Parameter inList inSortType inSortOrder inDelim Result Type Text Text Text Text Text Description Delimited list Not used, pass > or < List delimiter Modified list
version 3
Discussion This method sorts the elements of a list and returns a modified copy. If inSortOrder is > the elements are sorted in ascending order. If it is <, they are sorted , in descending order. If inDelim is not passed, it defaults to , .
438
Chapter 12
Standard Libraries
a4d.lists
Active4D v5
valueCount
valueCount(inList; inValue {; inDelim}) Number Parameter inList inValue inDelim Result Type Text <any> Text Number
version 3
Description Delimited list Value to match List delimiter Count of matching elements
Discussion This method counts how many elements of inList match inValue, doing a case- and diacritical-sensitive match. If inDelim is not passed, it defaults to , .
valueCountNoCase
valueCountNoCase(inList; inValue {; inDelim}) Number Parameter inList inValue inDelim Result Type Text <any> Text Number
version 3
Description Delimited list Value to match List delimiter Count of matching elements
Discussion This method counts how many elements of inList match inValue, doing a case- and diacritical-insensitive match. If inDelim is not passed, it defaults to , .
valueList
valueList(inField {; inDelim}) Text Parameter inField inDelim Result Type Field pointer Text Text
version 3
Description Field from which to get values List delimiter New list
Discussion This method returns a delimited list whose values are taken from the field pointed to by inField, one element for each record in the current selection of inFields table. inFields
Chapter 12
Standard Libraries
439
Active4D v5
a4d.lists
type must be convertible to text with the String command (which includes Alpha and Text fields). The selected record is not changed by this method. If inDelim is not passed, it defaults to , .
440
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
a4d.utils
This library is composed of various utility methods that do not generate HTML for output to a page.
Chapter 12
Standard Libraries
441
Active4D v5
a4d.utils
applyToSelection
version 4.5
applyToSelection(inTable; inStatement {; inTimeoutURL {; inTimeout}}) Boolean Parameter inTable inStatement inTimeoutURL inTimeout Result Type Table pointer Text Text Number Boolean Description Table to delete records from Code for APPLY TO SELECTION URL of page to redirect to on timeout Seconds to wait until timeout True if successfully applied
Discussion When using APPLY TO SELECTION in a multiuser database, it is of course important to ensure the entire selection is operated on, since some records may be locked. This method repeatedly tries to call APPLY TO SELECTION (using execute in 4d) for the table pointed to by inTable, until either no locked records remain or inTimeout seconds have elapsed. If no locked records remain, the method returns True. If the timeout is reached, the method returns False and the set LockedSet will contain the locked records. If inTimeout is not passed, it defaults to 2. If the timeout is reached and inTimeoutURL is passed and is not empty, a redirect is performed to that URL.
articleFor
articleFor(inNoun {; inBritishEnglish}) Text Parameter inNoun inVowelH Result Type Text Boolean Text
version 3
Discussion When generating messages in English, it is considered good form to use the proper article (a or an) with noun phrases.
442
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
If you need to generate a message with dynamically generated noun phrases, this method will return the proper article. If inVowelH is True, h will be considered a vowel sound as well. Example
method "whatAmI"($inKind) return ('You\'re `a4d.utils.articleFor($inKind)` $inKind') end method writebr(whatAmI("real peach")) writebr(whatAmI("idiot")) // -> You're a real peach // -> You're an idiot
blobToCollection
blobToCollection(inBlob; ioOffset; inGlobal) Collection Parameter inBlob ioOffset inGlobal Result Type BLOB Number Boolean Collection
v5.0
Description BLOB data saved with collectionToBlob Offset within inBlob to retrieve data True to create a global collection Deserialized collection
Discussion This method recursively deserializes a collection serialized with a4d.utils.collectionToBlob. On entry, ioOffset should point to the byte offset within inBlob at which the serialized collection data is stored (typically zero). On exit, ioOffset points to the first byte beyond the serialized collection data. If inGlobal is True, the collection returned is a global collection, otherwise it is a local collection.
blobToSession
blobToSession(inBlob; ioOffset) Parameter inBlob ioOffset Type BLOB Number
v5.0
Description BLOB data saved with collectionToBlob Offset within inBlob to retrieve data
Discussion This method is similar to the blob to session command, but it recursively deserializes a session serialized with a4d.utils.sessionToBlob. On entry, ioOffset should point to the
Chapter 12
Standard Libraries
443
Active4D v5
a4d.utils
byte offset within inBlob at which the serialized session data is stored (typically zero). On exit, ioOffset points to the first byte beyond the serialized session data. The deserialized session replaces the current session. For information on how this affects the current session, see blob to session on page 319.
camelCaseText
camelCaseText(inText {; inExceptions}) Text Parameter inText inExceptions Result Type Text Text Text Description Text to transform List of words to ignore Transformed text
version 4.0
Discussion This method changes the case of the words in inText so that the first character of the word is uppercase and the remaining letters are lowercase. Words that appear in the space-separated list inExceptions are completely lowercased. If inExceptions is not passed it defaults to the word list a at on in by .
write(a4d.utils.camelCaseText("this is a test")) // output -> This is a Test
chopText
chopText(inText) Text Parameter inText Result Type Text Text
version 4.0
Discussion This method chops inText into 80-character chunks separated by the string "+". The primary purpose of this method is to prepare text for use with the command execute in 4d. When calling that command, the equivalent of a 4D EXECUTE is performed. Since 4D limits the total length of a single literal string to 80 characters, this method ensures that the entire text passed to execute in 4d is executed.
444
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
Example
$sql := 'select trans.tran_key,splits.split_key,trans.amount as camount, splits.amount from trans,splits where trans.id = splits.tran_id and split_key = \'$invnum\'' $cmd := 'PgSQL Select(%d;"%s")' % ($connection; $sql) $rowset:= execute in 4d(a4d.utils.chopText($cmd); *)
collectionToBlob
collectionToBlob(inCollection; ioBlob) Parameter inCollection ioBlob Type Collection BLOB Description Collection to serialize BLOB to serialize to
v5.0
Discussion This method recursively serializes a collection and appends the serialized data to ioBlob. Numeric items or elements of numeric arrays are checked for validity as collection handles, and if they are valid the collections they point to are serialized. Example
$c := new collection("first"; "Tom"; "last"; "Bombadil") $c{"company"} := new collection("name"; "Acme Corp.") array longint($c{"company"}{"emps"}; 0) $emp := new collection("name"; "Sam Gamgee"; "age"; 47) $c{"company"}{"emps"}{} := $emp $emp := new collection("name"; "Frodo Baggins"; "age"; 53) $c{"company"}{"emps"}{} := $emp c_blob($blob) a4d.utils.collectionToBlob($c; $blob) // save $blob somewhere // in another script $offset := 0 $c := a4d.utils.blobToCollection($blob; $offset; false)
Note: If you serialize with this method, be sure to deserialize with a4d.utils.blobToCollection.
Chapter 12
Standard Libraries
445
Active4D v5
a4d.utils
cud
version 4.5
cud(cudAction; cudTable; cudProcessor {; attributes {; cudTimestampField {; cudTimestamp}}}) Text Parameter cudAction cudTable cudProcessor attributes cudTimestampField cudTimestamp Result Type Text Table pointer Text Collection Field pointer Text Text Description Action to perform Table to operate on Table-specific processing code Values to pass to cudProcessor Pointer to field holding a timestamp Current records timestamp Status of action
Discussion This method is a generalized processor for the most common operations on single records: creates, updates and deletes (hence the name cud). You supply a table-specific processing script and cud does the rest. There are four actions you can pass in cudAction: Action create update update* delete Description Create a new record Update an existing record Update a record if it exists, create a new record if not Delete an existing record
cudTable is a pointer to the table on which you wish to perform the operation. cud takes care of setting and restoring the read write state of the table. If cudProcessor begins with / it is taken to be a web root-relative path to an executable , script and is executed using include. Otherwise it is taken to be the name of an Active4D method (local or library) to execute. attributes is a collection containing values you wish to pass on to cudProcessor. Under fusebox, typically this would be the $attributes collection itself. If you are using timestamps to perform optimistic locking (see Using Timestamps with Optimistic Locking on page 368), you can have cud do the timestamp checking when updating or deleting records. If cudTimestampField is non-nil and cudTimestamp is nonempty, the current value of the field pointed to by cudTimestampField will be compared to cudTimestamp. cud returns a status which identifies the outcome of the operation. The built-in statuses returned by cud are: You may also define your own status values in cudProcessor. The only status that cud really pays attention to is success; any status other than that is considered failure.
446
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
Description The operation completed successfully The record could not be found Timestamp checking is being used and the timestamps do not match The record could not be unlocked
Phases For each action, there are several possible phases: query update delete post and , , , cleanup During each phase cudProcessor is executed, which gives you a chance to . customize cuds behavior accordingly. The details of each phase are covered below in the description of each actions flow of control. Custom processors Your custom processor needs to know the current state and return a status indicating success or failure. In the case of an include-based cudProcessor, cud communicates its current state via local variables. In addition to the parameters passed to cud itself (which appear as local variables and should be considered read only), there are two additional variables:
3 $cudPhase: This is set to the current phase of the requested action, and should be
considered read only. You use this variable to determine what to do in your processor.
3 $cudResult: This is set to the current status of the requested action, and may be
changed by your processor. You may abort the action before the post phase by setting this variable to a value other than success . In the case of a method-based cudProcessor, your method should be declared with the following signature:
method "myProccesor"($inAction; $inPhase; $inTable; $attributes; $inTimestampField; $inTimestamp)
The method should return a text status. You may abort the action before the post phase by returning a value other than success . If you want to maintain state in your cudProcessor between phases, it is recommended that you use the _request collection (see _request on page 300). Now we have seen all of the elements that go into making cud work. At this point it will be useful to examine the flow of control of each action in more detail. Create action The create action has four phases, in the following order:
3 query: Usually you will ignore this phase with the create action, since you dont
need to find an existing record in cudTable. But there may be cases where, for example,
Chapter 12
Standard Libraries
447
Active4D v5
a4d.utils
the creation of a record in cudTable is dependent on some value, either in a variable or in another table. In such cases you would check for the dependent value, and if the test fails you would set the status to missing or whatever error message you wish to use. , In this phase the read/write state of cudTable is whatever it was when cud was called (which is usually read only).
3 update: If the status is still success after the query phase, the update phase is
executed after CREATE RECORD is called and just before the newly created record is saved. In this phase cudTable will be read write and you must set cudTables fields to the appropriate values, typically retrieved from $attributes in a fusebox application, or from _query or _form in non-fusebox applications. If you want to use a transaction, you should start the transaction in this phase. If you want to abort the record creation, set the status to something other than success .
3 post: If the status is still success after the update phase, the post phase is
executed just after the new created record is saved. In this phase you would typically perform operations on related tables that depend on the existence of a record in cudTable, or you may need to wait for cudTables trigger to execute before performing some postprocessing.
3 cleanup: The cleanup phase is always executed, no matter what the status is. In this
phase you perform any last-minute processing, for example committing or cancelling a transaction based on the status. If you are not using transactions, most of the time you will ignore this phase. In this phase the read/write state of cudTable has already been restored to what it was before cud was called (usually read only). Update action The update action has the same four phases as the create action. The post and cleanup phases function identically to the create action. The query and update phases function as follows:
3 query: In this phase you must perform a query (or some other operation) that will
result in a selection of exactly one record in cudTable. If cudTable does not have exactly one record in its selection, cud will abort the action with a status of missing .
3 update: If the status is still success after the query phase, the update phase is
executed just before the record selected in the query phase is saved. Before this phase executes, cud has already set cudTable to read write and unlocked the record. In addition, if cudTimestampField was non-nil, cud has already verified that the records timestamp matches cudTimestamp. In this phase you must set cudTables fields to the appropriate values, typically retrieved from $attributes in a fusebox application, or from _query or _form in nonfusebox applications. If you want to use a transaction, you should start the transaction in this phase. If you want to abort the record update, set the status to something other than success .
448
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
Update* action The update* action has the same four phases as the update action. The post and cleanup phases function identically to the create action. The flow of control during the update* action is as follows: 1 2 3 4 The query phase is executed as if the action were update . If the query phase results in an empty selection in cudTable, cudAction is changed to create and then the action is restarted. If the query phase results in a selection of one record in cudTable, execution continues as if the action were update . If the query phase results in a selection of more than one record in cudTable, the action is aborted with a status of missing .
Delete action The delete action has four phases like the update action. The query post and , cleanup phases function identically to the update action. Instead of an update phase, there is a delete phase which functions as follows:
3 delete: If the status is still success after the query phase, the delete phase is
executed just before the record selected in the query phase is deleted. Before this phase executes, cud has already set cudTable to read write and unlocked the record. In addition, if cudTimestampField was non-nil, cud has already verified that the records timestamp matches cudTimestamp. In this phase you would typically update or delete related records. If there are no updates necessary outside of the main record deletion, you may ignore this phase. If you want to use a transaction, you should start the transaction in this phase. If you want to abort the record deletion, set the status to something other than success . Examples Lets take a look at an example. In this example, we have an application that tracks companies and contacts. Both use an edit form which receives the records id in the query string. If a new record is being created, the id is -1 .
Chapter 12
Standard Libraries
449
Active4D v5
a4d.utils
Here is the HTML (quite simplified for the sake of this example) for the company edit form:
<form action="<%=fusebox.makeURL($XFA_onSubmit)%>" method="post"> <% // $rs is a RowSet populated in a query fuse $rs->first $row := $rs->getRow a4d.web.hideField("id"; $attributes{"id"}) a4d.web.hideField("timestamp"; $row{"timestamp"}) %> Name: <input name="name" type="text" value="<%=$row{"name"}%>"/> <br/> Phone: <input name="phone" type="text" value="<%=$row{"phone"}%>"/> <br/> <input name="b_save" type="submit" value="Save" /> <input name="b_cancel" type="submit" value="Cancel" /> <input name="b_delete" type="submit" value="Delete" style="margin-left: 70px"/> </form>
When the a button is clicked and the form is posted, fusebox routes the request to an action fuse:
if ($attributes{"b_cancel"} # "") // Either delete or update with create if not found $action := choose($attributes{"b_delete"}; \\ "delete"; "update*") // Use a library method app.cudCompanies as processor, // and we want timestamp checking $result := a4d.utils.cud($action; ->[companies]; \\ "app.cudCompanies"; $attributes; \\ ->[companies]timestamp; $attributes{"timestamp"}) if ($result = "success") redirect(fusebox.makeURL($XFA_onSuccess)) else $query := build query string(""; "status"; $result) redirect(fusebox.makeURL($XFA_onFailure; $query)) end if else redirect(fusebox.makeURL($XFA_onCancel)) end if
450
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
That is all of the setup we need or cud. Now we take a look at our custom processor, the library method app.cudCompanies:
method "cudCompanies"($cudAction; $cudPhase; $cudTable; \\ $inStatus; $attributes; $cudTimestampField; $cudTimestamp) case of :($cudPhase = "query") query([companies]; [companies]id = $attributes{"id"}) :($cudPhase = "update") [companies]name := $attributes{"name"} [companies]phone := $attributes{"phone"} :($cudPhase = "delete") // contacts for this company now belong to the // special company "(None)" with id 0 if (not(a4d.utils.applyToSelection(->[contacts]; $code))) // oops, a contact record could not be unlocked return ("locked") end if end case return ("success") end method
As you can see, cud does most of the work and allows you to focus very tightly on the code that is specific to each table. Without cud you have to deal with the supporting logic, and you would end up copying, pasting and tweaking the same code for every table. Note: Just so we are all clear on this principle: copy, paste and tweak is a BAD THING. Dont do it. Use cud instead.
deleteSelection
deleteSelection(inTable {; inTimeoutURL {; inTimeout}}) Boolean Parameter inTable inTimeoutURL inTimeout Result Type Table pointer Text Number Boolean
version 3
Description Table to delete records from URL of page to redirect to on timeout Seconds to wait until timeout True if selection successfully deleted
Discussion When deleting a selection of records in a multiuser database, it is of course important to ensure the entire selection is deleted, since some records may be locked.
Chapter 12
Standard Libraries
451
Active4D v5
a4d.utils
This method repeatedly tries to delete the current selection in the table pointed to by inTable, until either no locked records remain or inTimeout seconds have elapsed. If no locked records remain, the method returns True. If the timeout is reached, the method returns False and the set LockedSet will contain the locked records. If inTimeout is not passed, it defaults to 2. If the timeout is reached and inTimeoutURL is passed and is not empty, a redirect is performed to that URL.
filterCollection
filterCollection(inCollection; inFilter {; inGlobal}) Collection Parameter inCollection inFilter inGlobal Result Type Collection | Iterator Text Boolean Collection
version 4.0
Description Collection to filter Filter specification True to return a global collection Filtered collection
Discussion This method filters a collection and returns a new, filtered collection. inFilter is matched against the keys of inCollection to determine which collection items are returned in the filtered collection. Each collection item whose key matches inFilter is copied to the filtered collection. If the first character of inFilter is +, the filter is an inclusion filter. If the first character is -, the filter is an exclusion filter. If there is no +/-, the filter defaults to an inclusion filter. If the first character after the optional +/- is /, the rest of the filter is taken as a regular expression, and should follow the rules for regular expression match strings (see regex match on page 253). Otherwise the normal string matching rules (@ is a wildcard) are in effect.
formatUSPhone
formatUSPhone(inPhone {; inFormat}) Text Parameter inPhone inFormat Result Type Text Text Text Description Phone number to format Format string for number Formatted phone number
version 3
Discussion Given a phone number in any format, this method will do the following:
452
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
3 Any non-numeric characters are removed. 3 If the remaining string is 11 digits and begins with 1 the 1 is removed. , 3 If the remaining string is 10 digits it is formatted according to inFormat. If inFormat is
not passed, the number is formatted as (000) 000-0000. Otherwise the number is formatted using the given format string using the % formatting operator. For example, to format the number as 000-000-000, pass a format of %s-%s-%s .
getMailMethod
getMailMethod Text Parameter Result Type Text
version 4.0
Discussion This method returns the name of the 4D method which is called by a4d.utils.sendMail to send a mail message. The default method is A4D_SendMail. For more information, see setMailMethod on page 461.
getPictureDescriptor
getPictureDescriptor(inPicture) Text Parameter inPicture Result Type Picture Text Description Picture to get info for Descriptive string
version 3
Discussion This method returns a string which describes the width, height, and byte size of inPicture. This is primarily useful in debugging.
Chapter 12
Standard Libraries
453
Active4D v5
a4d.utils
getPointerReferent
getPointerReferent(inPointer) Text Parameter inPointer Result Type Pointer Text
version 3
Discussion This method returns a string which identifies the referent of inPointer in the same way it would appear in the 4D debugger. In other words, the output for different pointer types is: Pointer type Table Field Variable Array element Result ->[table] ->[table]field ->var ->array{index}
getSMTPAuthorization
getSMTPAuthorization(outUserName; outPassword) Parameter outUserName outPassword Type Text Text
version 4.0
Discussion This method returns the current username and password that will be used to authorize SMTP access when calling sendMail. The username and password are set with setSMTPAuthorization.
454
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
getSMTPAuthPassword
getSMTPAuthPassword Text Parameter Result Type Text Description SMTP account password
version 4.0
Discussion This method returns the current password that will be used to authorize SMTP access when calling sendMail. The username and password are set with setSMTPAuthorization.
getSMTPAuthUser
getSMTPAuthUser Text Parameter Result Type Text
version 4.0
Discussion This method returns the current username that will be used to authorize SMTP access when calling sendMail. The username and password are set with setSMTPAuthorization.
getSMTPHost
getSMTPHost Text Parameter Result Type Text
version 4.0
Discussion This method returns the current hostname that will be used for SMTP access when calling sendMail. The SMTP host is set with setSMTPHost.
Chapter 12
Standard Libraries
455
Active4D v5
a4d.utils
nextID
nextID(inField {; inKeepSelection}) Text Parameter inField inKeepSelection Result Type Field Pointer Boolean Number
version 4.0
Discussion Given a pointer to a field which contains a Longint, Alpha or Text ID, this method returns the number which is one higher than the maximum value in that field. If inField is an Alpha or Text field, it is converted to a number with the Num command. If inKeepSelection is passed and is True, the current selection and record will be maintained. Otherwise they will be lost.
ordinalOf
ordinalOf(inNumber) Text Parameter inNumber Result Type Number Text Description Number to get ordinal for Number plus ordinal
version 3
Discussion This method returns inNumber suffixed with the correct suffix to make it an ordinal number.
456
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
Example
write(a4d.utils.ordinalOf(1)) write(a4d.utils.ordinalOf(10)) // -> 1st // -> 10th
parseConfig
parseConfig(inPathOrDocRef {; inEOL}) Collection Parameter inPathOrDocRef inEOL Type Text/Time Text
version 4.5
Discussion This method parses a text file with one or more lines in the form <key>=<value> into a collection. If inPathOrDocRef is of type Time, it must be a valid document reference to an open file that was opened with the Open document command. In this case you are responsible for closing the file after calling this method. Otherwise inPathOrDocRef should be a text path to the config file you want to parse. The path should follow the rules or paths used with the Open document command. If the file is successfully opened, it is automatically closed before this method returns. If the file cannot be opened, an empty collection is returned. If inEOL is not passed, the line endings are assumed to be LF (\n). If your config file has line endings other than LF, you must pass the line ending in inEOL. The last line of the config file does not need to be terminated with a line ending. Blank lines and white space around the keys and values are discarded. In addition, if the first characters of a line are (4D comment character) or // (Active4D line comment characters), the line is ignored. This allows you to comment the config file. Examples Lets assume a site we are developing has to send emails. During testing, we do not want the emails to go to the intended recipients, we want them to come to us. In addition, the SMTP host on the deployment server is different than the one we use during testing. Instead of hard coding hostnames and email addresses into our code, we can use a config file. We decide to put a file called mail.ini in the database directory. Heres what our config file might look like:
Chapter 12
Standard Libraries
457
Active4D v5
a4d.utils
// // // // // //
Use this file to configure the settings for your mail server. If you want to force mail to go to a certain address, enter the "to" address here. To use the normal destination address, leave the "to" value empty. If a "to" address is entered here, the mail message will display the original "to" address.
To ensure our config file is accessible, we set the safe doc dirs option in Active4D.ini:
safe doc dirs = <default>
In the On Application Start method in the Active4D library, we add this code:
$path := join paths(default directory(*); "mail.ini") $config := a4d.utils.parseConfig($path) a4d.utils.setSMTPHost($config{"host"}) globals{"mail.to"} := $config{"to"}
458
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
reverseArray
reverseArray(ioArray) Parameter ioArray Type Array Description Array to reverse
version 3
sendMail
Discussion This method is a front end to the 4D method A4D_SendMail that makes it easy to dynamically generate email messages. If the first character of inMailFile is not !, it is considered a path to a file to include, relative to the file that called this method. Because the file in included within the context of this method, the callers local variables are not available. To access the callers local variables, put the values you want to access in a collection and pass that collection in inUserData. The output of the include becomes the source of the email message. If the first character of inMailFile is !, the text following it is executed using the Active4D execute command. Any output from that execution that would normally go to the response buffer is saved and becomes the source of the email message. If the first character of inMailFile is |, the text following it becomes the source of the email message.
Chapter 12
Standard Libraries
459
Active4D v5
a4d.utils
The first line of the email source is taken as the subject of the message, and must be separated from the body of the message by a linefeed (\n). Thus you must save an include file with Unix line endings when you edit it. The rest of the email source becomes the body of the message. inTo, inCc, and inBcc can all contain more than one address, separated by commas. To add an attachment, pass the full Unix-style path to the attachment in inAttachmentPath. If inHeaders is passed, it should be a linefeed-delimited list of header:value pairs. Note: Before using this command you must call setSMTPHost, and setSMTPAuthorization if the SMTP host requires account authorization. Also, the subject must be separated from the body by a linefeed ("\n"), not a carriage return ("\r"). Example When a new user logs into the system, we want to send a welcome email with their user information. Here is the email include file called welcome.inc:
Welcome to ACME Corporation! Dear <%=$inUserData{"firstname"}%>, Welcome to the growing family of ACME Corporation members. Your login information is as follows: username: <%=$inUserData{"username"}%> password: <%=$inUserData{"password"}%> To login, please go to www.acme.com/login. Regards, ACME Corporation
To generate the email, we first do a query that generates a RowSet with the columns email username password and firstname We then pass this to sendMail: , , , .
$map := """ email: [users]email;firstname:[users]firstname; username:[users]username;password:[users]password""" $rs := RowSet.NewFromSelection(->[users]; $map) $rs->first $row := $rs->getRow a4d.utils.sendMail("email/welcome.inc"; "sales@acme.com"; \\ $row{"email"}; ""; ""; ""; $row; \\ "Reply-To: noreply@acme.com")
460
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
sessionToBlob
sessionToBlob(ioBlob) Parameter ioBlob Type BLOB Description BLOB to serialize to
v5.0
Discussion This method recursively serializes the current session and appends the serialized data to ioBlob. Numeric items or elements of numeric arrays are checked for validity as collection handles, and if they are valid the collections they point to are serialized. Note: If you serialize with this method, be sure to deserialize with a4d.utils.blobToSession.
setMailMethod
setMailMethod(inMethod) Parameter inMethod Type Text Description 4D method name
version 4.0
Discussion This method sets the name of the 4D method which is called by a4d.utils.sendMail to send a mail message. The default method is A4D_SendMail. If you specify a method other than A4D_SendMail, its parameters must be identical in position and type to A4D_SendMail. A4D_SendMail uses 4D Internet Commands to send email immediately. If you want to use some other method to send email, for example if you want to queue the mail for later delivery or use some other plugin to send mail, you can use setMailMethod to call your own custom method.
Chapter 12
Standard Libraries
461
Active4D v5
a4d.utils
setSMTPAuthorization
setSMTPAuthorization(inUserName; inPassword) Parameter inUserName inPassword Type Text Text
version 4.0
Discussion This method sets the username and password that will be used to authorize SMTP access when calling sendMail.
setSMTPHost
setSMTPHost(inHost) Parameter inHost Type Text Description SMTP hostname
version 4.0
Discussion This method sets the hostname that will be used for SMTP access when calling sendMail.
truncateText
truncateText(inText; inWidth; inTruncateMode) Text Parameter inText inWidth inTruncateMode Result Type Text Number Number Text Description Text to truncate Width to truncate to How to truncate Truncated text
version 4.0
Discussion This method truncates inText to the character width specified by inWidth. If Length(inText) < 3 or Length(inText) < inWidth, inText is returned as is. Otherwise Length(inText) - inWidth characters are removed from inText and are replaced by an ellipsis (...). The placement of the ellipsis is controlled by inTruncateMode. There are three modes which are defined as library constants:
462
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
Truncate modes kTruncateText_Start kTruncateText_Middle kTruncateText_End Example If you know you will have a very long string, such as a file path, you may want to display only part of it onscreen, like so:
$path := "/Home/Users/Spock/Documents/biz/webapps/contacts/docs" write(a4d.utils.truncateText($path; 20; \\ a4d.utils.kTruncateText_Start)) // -> ...ebapps/contacts/docs write(a4d.utils.truncateText($path; 20; \\ a4d.utils.kTruncateText_Middle)) // -> /Home/User...tacts/docs write(a4d.utils.truncateText($path; 20; \\ a4d.utils.kTruncateText_End)) // -> /Home/Users/Spock/Do...
unlockAndLoad
Discussion This method tries repeatedly to load an unlocked copy of the record with the record number inRecNum in the table pointed to by inTable, until either the record becomes unlocked or inTimeout seconds elapses. Basically, you should be using this method any time you need to update a record. If inRecNum is not passed or is -1, the current record in the table pointed to by inTable is used. If inTimeout is not passed, by default unlockAndLoad will wait 2 seconds before timing out. If inTimeoutURL is passed in and is non-empty, after a timeout a redirect will be performed to that URL.
Chapter 12
Standard Libraries
463
Active4D v5
a4d.utils
If the record is successfully unlocked, True is returned and the table pointed to by inTable is left in read write mode. If a timeout occurs while waiting for a lock, the read only state of the table is restored to what it was before the method was called, and if inTimeoutURL is empty False is returned. Example A typical scenario is the posting of an edit form for a record. In the form processing script you need to update the record. Typically you would do something like this:
query([contacts]; [contacts]id = $attributes{"cid"}) if (records in selection([contacts]) = 1) if (a4d.utils.unlockAndLoad(->[contacts])) [contacts]email := $attributes{"f_email"} [contacts]phone := $attributes{"f_phone"} save record([contacts]) unload record([contacts]) read only([contacts]) end if end if
validPrice
validPrice(inPrice; inCurrencyMark; inDecimalSep) Boolean Parameter inPrice inCurrencyMark inDecimalSep Result Type Number/Text Text Text Boolean
Description Price to check Optional currency mark to allow, defaults to "$" Decimal separator character, defaults to "." True if inPrice fits the pattern
Discussion This method validates the format of a price. If inPrice is a number, it is converted to a string with two decimal places and the decimal separator inDecimalSep.
464
Chapter 12
Standard Libraries
a4d.utils
Active4D v5
yearMonthDay
yearMonthDay({inShortDate {; inDate}}) Text Parameter inShortDate inDate Result Type Boolean Date Text
Description True to use 2-digit year, defaults to False Date to format, defaults to current date Formatted date
Discussion This method converts inDate to the format YYYYMMDD if inShortDate is False or is not passed. If inShortDate is passed and is True, inDate is converted to the format YYMMDD. If inDate is not passed or is !00/00/00!, it defaults to the current server date.
Chapter 12
Standard Libraries
465
Active4D v5
a4d.web
a4d.web
This library is composed of methods that are primarily designed to make it easier to work with forms, query strings, and SELECT lists. Note: The dump <something> methods have been moved to a separate a4d.debug library.
466
Chapter 12
Standard Libraries
a4d.web
Active4D v5
buildOptionsFromArrays
buildOptionsFromArrays(inOptions; inValues; inInitialIndex {; inInitialValue}) Parameter inOptions inValues inInitialIndex inInitialValue Type Array Array Number <any>
version 3
Description Option texts Option values Index of option to select, 0 to use inInitialValue Value of option to select
Discussion This method writes a series of HTML OPTIONs to the output buffer, one for each element in the inOptions array. The text of each OPTION comes from inOptions, and the value comes from inValues. Both inOptions and inValues can be any type to which the String command can be applied to its elements (which includes String/Text Arrays). If inSelect is passed in, it must be assignment compatible with inValues. If inInitialIndex > 0, it is used as the starting index and inInitialValue is ignored. Note that this method only builds the OPTIONs of a SELECT object, not the SELECT object itself. Note: This method was previously called buildArrayValueList, which will continue to work in this release but is now deprecated. Example Given arrays of country names and codes that you have cached in the globals collection, you could build a select list that would default to United States as the country and would return the country code like this:
<select name="f_country" id="f_country" size="1"> <% a4d.web.buildOptionsFromArrays(globals{"country_names"}; \\ globals{"country_codes"}; 0; "US") %> </select>
Chapter 12
Standard Libraries
467
Active4D v5
a4d.web
buildOptionsFromLists
version 3
buildOptionsFromLists(inOptions; inValues; inInitialIndex {; inInitialValue {; inDelimiter}}) Parameter inOptions inValues inInitialIndex inInitialValue inDelimiter Type Text Text Number Text Text Description Delimited list of option texts Delimited list of option values Index of option to select, 0 to use inInitialValue Value of option to select List delimiter, defaults to ;
Discussion This method writes a series of HTML OPTIONs to the output buffer, one for each element in the inOptions list. The text of each OPTION comes from inOptions, and the value comes from inValues. If inInitialIndex > 0, it is used as the starting index and inInitialValue is ignored. Note that this method only builds the OPTIONs of a SELECT object, not the SELECT object itself. Note: This method was previously called buildSelectValueMenu, which will continue to work in this release but is now deprecated. Example To build a choice list of US states and select the first state by default, you could do the following:
<select name="f_state" id="f_state" size="1"> <% a4d.web.buildOptionsFromLists( \\ a4d.web.kUS_SortedStateNames; \\ a4d.web.kUS_UnsortedStateCodes; 1) %> </select>
468
Chapter 12
Standard Libraries
a4d.web
Active4D v5
buildOptionsFromOptionArray
buildOptionsFromOptionArray(inOptions; inInitialIndex {; inInitialValue}) Parameter inOptions inInitialIndex inInitialValue Type Array Number <any>
version 3
Description Contains option texts Index of option to select, 0 to use inInitialValue Value of option to select
Discussion This method writes a series of HTML OPTIONs to the output buffer, one for each element in the inOptions array. The text of each OPTION comes from inOptions. If inInitialIndex > 0, the value of each OPTION is its index. If inInitialIndex > 0, the value of each OPTION comes from inOptions. inOptions can be any type to which the String command can be applied to its elements (which includes String/Text Arrays). If inInitialValue is passed in, it must be assignment compatible with inOptions. If inInitialIndex > 0, it is used as the starting index and inInitialValue is ignored. Note that this method only builds the OPTIONs of a SELECT object, not the SELECT object itself. Note: This method was previously called buildArrayList, which will continue to work in this release but is now deprecated. Example To build a choice list of cached status codes, you could do this:
<select name="f_status" id="f_status" size="1"> <% a4d.web.buildOptionsFromOptionArray( \\ globals{"customer.status"}; 0; $row{"status"}) %> </select>
Chapter 12
Standard Libraries
469
Active4D v5
a4d.web
buildOptionsFromOptionList
buildOptionsFromOptionList(inOptions; inInitialIndex {; inInitialValue}) Parameter inOptions inInitialIndex inInitialValue Type Text Number Text
version 3
Description Delimited list of option texts Index of option to select, 0 to use inInitialValue Value of option to select
Discussion This method writes a series of HTML OPTIONs to the output buffer, one for each element in the inOptions list. The text of each OPTION comes from inOptions. If inInitialIndex > 0, the value of each OPTION is its index. If inInitialIndex > 0, the value of each OPTION comes from inOptions. If inInitialIndex > 0, it is used as the starting index and inInitialValue is ignored. Note that this method only builds the OPTIONs of a SELECT object, not the SELECT object itself. Note: This method was previously called buildSelectMenu, which will continue to work in this release but is now deprecated. Example To build a choice list of US state codes that defaults to the first state, you could do this:
<select name="f_state" id="f_state" size="1"> <% a4d.web.buildOptionsFromOptionArray( \\ a4d.web.kUS_State; 1) %> </select>
470
Chapter 12
Standard Libraries
a4d.web
Active4D v5
buildOptionsFromRowSet
version 4.0
buildOptionsFromRowSet(inRowSet; inOptionColumn; inValueColumn; inInitialIndex {; inInitialValue}) Parameter inRowSet inOptionColumn inValueColumn inInitialIndex inInitialValue Type RowSet Text Text Number Text Description Rows from which to get data Name of column which contains option texts Name of column which contains option values Index of option to select, 0 to use inInitialValue Value of option to select
Discussion This method writes a series of HTML OPTIONs to the output buffer, one for each row in inRowSet. The text of each OPTION comes from the column inOptionColumn. The value of each OPTION comes from the column inValueColumn if inValueColumn is not an empty string, or from the column inOptionColumn otherwise. If inInitialIndex > 0, it is used as the starting index and inInitialValue is ignored. Note that this method only builds the OPTIONs of a SELECT object, not the SELECT object itself. Example To build a multiple choice list of sport names and codes that defaults to nothing selected, you could do this:
<select name="f_sports" id="f_sports" size="10" multiple="multiple"> <% a4d.web.buildOptionsFromRowSet($rsSports; "name"; "code"; -1) %> </select>
Chapter 12
Standard Libraries
471
Active4D v5
a4d.web
buildOptionsFromSelection
buildOptionsFromSelection(inOptionField; inValueField; inInitialValue) Parameter inOptionField inValueField inInitialValue Type Field pointer Field pointer <any>
version 3
Description Points to option texts Points to option values Value of option to select initially
Discussion This method writes a series of HTML OPTIONs to the output buffer, one for each record in the current selection of inValueFields table. The text of each OPTION comes from inOptionField. The value of each OPTION comes from inValueField. If String(inValueField->) evaluates to 0 the option text is set to <Default> , . Note that this method only builds the OPTIONs of a SELECT object, not the SELECT object itself. Note: This method was previously called buildRecordList, which will continue to work in this release but is now deprecated. Also note that buildRecordList reversed the order of inOptionField and inValueField. Example To build a choice list of vendor names and IDs that defaults to the first one selected, you could do this:
<select name="f_vendors" id="f_vendors" size="1"> <% a4d.web.buildOptionsFromSelection( \\ ->[vendors]name; ->[vendors]id; [vendors]id) %> </select>
472
Chapter 12
Standard Libraries
a4d.web
Active4D v5
checkSession
checkSession(inItemToCheck; inRedirectURL {; inQueryString}) Parameter inItemToCheck inRedirectURL inQueryString Type Text Text Text
version 3
Description Name of item to check for in session URL of page to redirect to Query string to pass on redirect
Discussion It is important that you detect when a session has timed out or when no session exists. This is easily done by designating one session item (such as a user id) which only exists when a user has successfully logged in to the site. You then need to check the session before displaying every page that relies on a current session. This method is a convenience method for checking the session. You pass the designated session item in inItemToCheck. If the item does not exist, a redirect is performed to inRedirectURL, passing inQueryString. Note: If you are using Fusebox, do not use this method. Example
<% checkSession("user.id"; "/timeout.a4d") %>
checkboxState
checkboxState(inState) Parameter inState Type Boolean | Text Description State of a checkbox
version 3
Discussion This method makes it easier to set dynamic checkboxes in your pages. If inState is a Boolean and True, or if it is text and is 1 the text checked="checked" is written to the , output buffer. Example Suppose you have a series of checkboxes on a form that reflect data from a RowSet. You could set them like this:
<input name="f_dorm" id="f_dorm" type="checkbox" <%checkboxState($row{"dorm"})%>> Will live in dorm
Chapter 12
Standard Libraries
473
Active4D v5
a4d.web
collectionItemsToQuery
collectionItemsToQuery(inCollection; inItems {; inSwitches}) Text Parameter inCollection inItems inSwitches Result Type Collection | Iterator Text Text Text
version 3
Description Collection from which to get items Semicolon-delimited list of item keys Switches to control query formatting Query string
Discussion This method constructs a query string (without a leading ?) from the items in inCollection whose keys match the keys in the semicolon-delimited list inItems. White space around the key names in inItems is automatically trimmed. inSwitches determines the formatting of the query string, and follows the same format as the switches passed to build query string. For more information, see build query string on page 247. Example When you are displaying a page that is based on some contextual information derived from a posted form or the query string, you usually need to maintain that contextual information in any links which exit the page. For example, consider the following typical drill-drown scenario:
3 The user selects a company 3 From a list of contacts in the company, a contact is clicked on to view his or her details 3 From a list of phone calls, one call is clicked on to view the details of the call
At each step along the way, you want to know the full context so you know how the user got to where they are and how they can get back. So you need to carry the context information (such as company ID / contact ID / call ID) forward as the user drills down. This method makes it easy to construct links with query strings that contain all the context information you need. In the company/contacts/phone calls example cited above, the links to display a call detail might look like this:
<% // We are using Fusebox, so the query string for this // page is in $attributes // cid = company id, ctid = contact id $query := a4d.web.collectionItemsToQuery($attributes; \\ "cid;ctid") %> <a href="<%=fusebox.makeLink($XFA_onViewCallDetail; $query)%>" title="View call detail">$row{"number"}</a>
474
Chapter 12
Standard Libraries
a4d.web
Active4D v5
collectionToQuery
collectionToQuery(inCollection {; inFilter}) Text Parameter inCollection inFilter Result Type Collection | Iterator Text Text
version 4.0
Description Collection from which to get items Text to match against Query string
Discussion This method is identical to embedCollection, but instead of creating hidden form fields, constructs a query string (without a leading ?) from the items in inCollection whose keys match the filter specified by inFilter. For more information on how the filtering works, see embedCollection on page 475.
embedCollection
embedCollection(inCollection {; inFilter}) Parameter inCollection inFilter Type Collection | Iterator Text
version 3
Discussion When you are displaying a form that is based on some contextual information derived from a posted form or the query string, you usually need to maintain that contextual information in hidden fields within the form, so that when the form is posted you can determine the context. For example, consider the following typical scenario:
3 The user selects a company 3 From a list of contacts in the company, a contact is clicked on to view his or her details
At each step along the way, you want to know the full context so you know how the user got to where they are and how they can get back. So you need to carry the context information (such as company ID / contact ID) forward as the user navigates through the data.
Chapter 12
Standard Libraries
475
Active4D v5
a4d.web
If all of the context information is in a single collection, and the keys of the collection items can be included or excluded by a pattern, this method makes it easy to embed all of the context information you need within a form. Note: If the keys of the items you want to embed do not follow a pattern (which is often the case), use embedCollectionItems instead of this method. inFilter is matched against the keys of inCollection to determine which collection items are embedded in the form. For each collection item whose key matches inFilter, a hidden form field is created whose id/name is the item key and whose value is the item value. If a collection item is an array, a hidden form field will be created for each element of the array. If the first character of inFilter is +, the filter is an inclusion filter. If the first character is -, the filter is an exclusion filter. If there is no +/-, the filter defaults to an inclusion filter. If the first character after the optional +/- is /, the rest of the filter is taken as a regular expression, and should follow the rules for regular expression match strings (see regex match on page 253). Otherwise the normal string matching rules (@ is a wildcard) are in effect. Example In the company/contacts example cited above, the edit form for the contact might look like this:
<form id="form" name="form" action="<%=fusebox.makeURL($XFA_onSubmit)%>" method="post" > <div> <input id="f_name" name="f_name" type="text" value="<%=$row{"name"}%>" /><br /> <input id="f_phone" name="f_phone" type="text" value="<%=$row{"phone"}%>" /><br /> <input id="x_submit" name="x_submit" type="submit" value="Save" /> <% // embed the context a4d.web.embedCollection($attributes; "f_@") %> </div> </form>
476
Chapter 12
Standard Libraries
a4d.web
Active4D v5
embedCollectionItems
embedCollectionItems(inCollection; inItems) Parameter inCollection inItems Type Collection | Iterator Text
version 3
Description Collection from which to get items Semicolon-delimited list of item keys
Discussion This method serves the same purpose as collectionItemsToQuery, but instead of returning a query string, embeds the items as hidden form items. For more details see the discussion for collectionItemsToQuery.
embedFormVariableList
embedFormVariableList(inItems) Parameter inItems Type Text
version 3
embedFormVariables
embedFormVariables({inFilter}) Parameter inFilter Type Text Description Text to match against
version 3
Chapter 12
Standard Libraries
477
Active4D v5
a4d.web
embedQueryParams
embedQueryParams({inFilter}) Parameter inFilter Type Text Description Text to match against
version 3
embedVariables
embedVariables({inFilter}) Parameter inFilter Type Text Description Text to match against
version 3
For more information, see the discussion of embedCollection on page 475 and getVariablesIterator on page 480.
478
Chapter 12
Standard Libraries
a4d.web
Active4D v5
formVariableListToQuery
formVariableListToQuery(inVariables {; inSwitches}) Parameter inVariables inSwitches Type Text Text
version 3
Description Semicolon-delimited list of form variables Controls the formatting of the query
If inSwitches is not passed, it defaults to an empty string. For more information, see the discussion of collectionItemsToQuery on page 474.
getEmptyFields
getEmptyFields(inFieldList) Text Parameter inFieldList Result Type Text Text
version 3
Description Semicolon-delimited list of form fields to validate Semicolon-delimited list of empty fields
Discussion This method checks the form variables collection for each field named in the list inFieldList. If the field does not exist or is empty, it is added to the result list.
Chapter 12
Standard Libraries
479
Active4D v5
a4d.web
getUniqueID
getUniqueID Text Parameter Result Type Text
version 3
Discussion Sometimes it is necessary to force (lousy) browsers or proxy caches into thinking that the same page is a new page in order to prevent the page from being cached. The simplest way to do this is to append a unique query parameter to the query string of the URL. This forces clients to think it is a different page. This method will give you a per-request unique identifier that you can put into a query string.
getVariablesIterator
getVariablesIterator Iterator Parameter Result Type Iterator Description Either _form or _query
version 3
Discussion This method returns an iterator for the collection in which values were passed to the current page. In other words, whether the current page was reached via a link, a form posted with the get method, or a form posted with the post method, this method will return an iterator that gives you access to the query string or form variables appropriately.
480
Chapter 12
Standard Libraries
a4d.web
Active4D v5
hideField
hideField(inName; inValue {; inEncode}) Parameter inName inValue inEncode Type Text <any> Boolean
version 3
Description Name/id of hidden field Value of hidden field True to HTML encode inValue
Discussion This method writes an XHTML-compatible hidden form field to the output buffer. inValue must be convertible by the String command (which includes strings/text). If inEncode is not passed or is passed and is True, inValue is HTML encoded.
hideUniqueField
hideUniqueField(inName) Parameter inName Type Text Description Name/id of hidden field
version 3
Discussion This method writes an XHTML-compatible hidden form field to the output buffer with a per-request unique value. For more information see getUniqueID on page 480.
saveFormToSession
saveFormToSession({inFilter}) Parameter inFilter Type Text Description Text to match against
version 3
Discussion If you want to save one or more form variables to the session, and the form variable names can be included or excluded by a pattern, this method makes it easy to do so. inFilter is matched against the names of the form variables to determine which ones are saved in the session. For each form variable whose name matches inFilter, a session item is created whose key is the form variable name and whose value is the form variable value.
Chapter 12
Standard Libraries
481
Active4D v5
a4d.web
If the first character of inFilter is +, the filter is an inclusion filter. If the first character is -, the filter is an exclusion filter. If there is no +/-, the filter defaults to an inclusion filter. If the first character after the optional +/- is /, the rest of the filter is taken as a regular expression, and should follow the rules for regular expression match strings (see regex match on page 253). Otherwise the normal string matching rules (@ is a wildcard) are in effect.
validateTextFields
validateTextFields(inFieldList) Text Parameter inFieldList Result Type Text Text
version 3
Description Semicolon-delimited list of form fields to validate Semicolon-delimited list of empty fields
Discussion This method is an alias for getEmptyFields. Note: This method is deprecated. Please use getEmptyFields instead.
validEmailAddress
validEmailAddress(inAddress) Boolean Parameter inAddress Result Type Text Boolean
Discussion This method validates that inAddress is valid using a regular expression that should cover the vast majority of possible email addresses. Note: Full validation according to RFC822 would require a regular expression that is 6K characters in length!
482
Chapter 12
Standard Libraries
a4d.web
Active4D v5
warnInvalidField
warnInvalidField(inCurrentField; inInvalidField; inWarningURL) Parameter inCurrentField inInvalidFields Type Text Text
version 3
Description The current field being checked Semicolon-delimited list of invalid form fields
Discussion $inCurrentField->TextThe current field we are checking $inInvalidFields->TextSemicolon-delimited list of invalid form fields $inWarningURL->TextURL of warning icon to display
If $inCurrentField is in the list $inInvalidFields, an image tag is written to display $inWarningURL. The format of $inInvalidFields is that returned by the ValidateTextFields method. This method validates that inAddress is valid using a regular expression that should cover the vast majority of possible email addresses
writeBold
writeBold(inText; inTest) Parameter inText inTest Type Text Boolean
Discussion This method writes inText to the response buffer. If inTest is True, inText is enclosed in a <strong></strong> tag pair. <strong> is used because it is preferred by web designers. <b> is a font weight, whereas <strong> conveys the meaning you want to impart to inText by changing its style.
Chapter 12
Standard Libraries
483
Active4D v5
Batch
Batch
One of the most common tasks in a dynamic website is the display of columnar data following a query, much as you would display a listing form within 4D. It is bad user interface design to display much more than one or two screens of data at one time. This means that you have to split the total number of data rows into batches and give the user a means of paging through them, much as you do when paging through the results of a google search. The Batch library is designed to make the process of generating batches as simple as possible. In addition, it provides one-line methods for generating the HTML links necessary to go from one page to another. Batches dont know anything about the nature of the rows they are batching. They have no access to the data. Their sole purpose in life is to deal with indexes into the rows of data. You must use those indexes to fetch the data from whatever data source you are using, be it a RowSet, table selection, or array.
Batch Attributes
A batch is an object-like thing that is represented by a collection. The collection contains several numeric attributes that control the behavior of the batch. Note: You should consider batch attributes read-only. Dont try changing them once the batch is created unless you want unexpected results. In order to use batches effectively, you need to understand their attributes: Attribute size row_count start end orphan overlap Description Number of rows per batch Number of rows managed by batch Starting index of the batch Ending index (inclusive) of the batch Minimum batch size (maximum orphans) How many rows to overlap in each batch
Creating a Batch
Batches are created from a set of rows. Those rows can come from a RowSet, a table selection, or an array. So to create a batch object you call the appropriate method in the Batch library.
484
Chapter 12
Standard Libraries
Batch
Active4D v5
To create a batch from a RowSet, you use the newFromRowSet method (surprise, surprise), like this:
$batch := Batch.newFromRowSet($rowset; $attributes)
After calling these methods, you get back a batch object that contains the attributes listed above. Typically the only attributes you are interested in are the start, end and row_count attributes.
To calculate the starting and ending indexes for the batch, the Batch library uses the following logic:
3 If start is known and is > 0, it is used as the starting index. Otherwise the starting index
is 1.
3 If the next batch would contain less than orphan elements, it is combined with the
current batch.
3 overlap is the number of rows shared by adjacent batches. 3 If size is <= 0, it is computed from start and end. Failing that, it is the default size. 3 If end is not specified or is <= 0, it is computed from the other parameters.
Batch Defaults Typically, all of the batches in a given site will share the same size, minimum size (orphan), and overlap. The batch library allows you to set defaults for these values so that you do not have to specify them each time you create a batch.
Chapter 12
Standard Libraries
485
Active4D v5
Batch
When the Batch libary is first imported, the following defaults are set: Parameter size orphan overlap start param Default 10 2 0 bst
You may set the defaults by calling Batch.setDefaults. Typically you would do this in the On Application Start event handler in Active4D.a4l. If you do not specify the start index when creating a batch, you must pass one of the newFromX methods a collection handle or iterator which contains the default start param. Since the batch start index is usually kept in the query string, in a Fusebox application you would pass $attributes, as in the examples above, and in a non-Fusebox application you would usually pass _query. Lets look at some examples to see how this works. Lets assume we have a RowSet that has 30 rows. We have a batch size of 10, a minimum batch size (orphan) of 3, and an overlap of 1. We will end up with 3 batches: Batch # 1 2 3 Start - end indexes 1 - 10 10 - 19 19 - 30
Okay, lets analyze whats happening here. In the first batch, the starting index is 1, and the size is 10, so obviously we will get rows 1-10. The last <batch overlap> rows of the each batch are repeated at the beginning of the next batch. So in the second batch, because we have an overlap of 1, the first row is row 10. A total of 10 rows takes us up to 19 as the ending index (not 20, that would be 11 rows). Applying the same overlap trick to the third batch, we start at index 19 and add 9 to get a total of 10 rows. This takes us to an ending index of 28. But since the orphan (minimum) size is 3 and there are only 2 rows left, the final 2 rows are added to the end of the third batch, which gives us an ending index of 30. In this case examining the size attribute of the batch would reveal a size of 12.
486
Chapter 12
Standard Libraries
Batch
Active4D v5
The hard way is to iterate through the batches and build the links yourself, like this:
array longint($starts; 0) $batch->getStarts($starts) c_longint($i) for ($i; 1; size of array($starts)) if ($i = $starts) // current batch // build link for current batch else // build link for other batches end if end for
That may not look so hard, but the code to build the links is not trivial. Its so non-trivial Im too lazy to bother including it here, because all that work is done for you if you take the easy road, like this:
<% c_text($prev; $batches; $next) $needBatch := $batch->makeFuseboxLinks($prev; $batches; $next; \\ $attributes) %> // later, when you need to display the links <% if ($needBatch) %> <div id="batches"> Go to page: <%=$prev + $batches + $next%> </div> <% end if %>
The easy way has a little more code here, but only because I am leaving so much out of the hard way, which in reality would have 10 times more code code that you would end up copying and pasting all over the place. The makeFuseboxLinks method and its non-Fusebox cousin, makeLinks, allow you to customize everything necessary to format the page links exactly the way you want, so you should never have to do it yourself. Batch Defaults for Generating Links To format the batch links, the Batch library needs the following parameters: Parameter previous separator next tag max Description HTML|CSS to use for first and previous link HTML to use between page numbers HTML|CSS to use for next and last link Default « Previous|batch-prev Next »|batch-next
HTML tag to use for the current batch strong Maximum batches to display 7
Chapter 12
Standard Libraries
487
Active4D v5
Batch
The defaults are set for you when the Batch library is imported. If you wish to change the defaults, you may do so with the Batch.setDefaults method. When you call makeFuseboxLinks or makeLinks, to use the default values either omit parameters or pass empty strings or negative numbers, as is done in the example above.
488
Chapter 12
Standard Libraries
Batch
Active4D v5
Chapter 12
Standard Libraries
489
Active4D v5
Batch
dumpDefaults
dumpDefaults
version 4.0
Discussion This method produces a formatted dump of the current default parameters. For a discussion of the purpose of each parameter, see Batch Defaults on page 485 and Batch Defaults for Generating Links on page 487.
getDefaults
version 4.0
getDefaults(outSize; outMinSize; outOverlap; outMaxBatches; outPrevious; outSeparator; outNext; outCurBatchTag; outStartParam) Parameter outSize outMinSize outOverlap outMaxBatches outPrevious outSeparator outNext outCurBatchTag outStartParam Type Number Number Number Number Text Text Text Text Text Description Receives batch size Receives batch minimum size Receives batch overlap Receives maximum batches to display Receives previous batch HTML Receives batch separator HTML Receives next batch HTML Receives HTML tag for current batch Receives start index parameter name
Discussion This method retrieves the current defaults for all values used by the Batch library. For a discussion of the purpose of each parameter, see Batch Defaults on page 485 and Batch Defaults for Generating Links on page 487.
490
Chapter 12
Standard Libraries
Batch
Active4D v5
getStarts
getStarts(self; outStarts) Parameter self outStart Type Batch Array Longint
version 4.0
Discussion This method gets the starting indexes for every batch that can be generated for the set of rows referred to by self. The current element of outStarts is set to the current batch number.
makeFuseboxLinks
makeFuseboxLinks(self; ioPrevious; ioBatches; ioNext; inAttributes {; inXFA {; inPassedAttrs {; inCurBatchTag {; inStartParam {; inMaxBatches}}}}}) Boolean Parameter self ioPrevious ioBatches ioNext inAttributes inXFA inPassedAttrs inCurBatchTag inStartParam inMaxBatches Result Type Batch Text Text Text Collection Text Text Text Text Number Boolean
version 4.0
Description The batch object On entry, the HTML text for the first/previous batch link On entry, the HTML text to insert between batch numbers On entry, the HTML text for the next/last batch link Fusebox $attributes collection The XFA to link to Semicolon-delimited list of attributes to pass in the links Tag to enclose current batch in Query parameter name for start index Maximum number of batches to display True if links are needed
Discussion This method is the same as makeLinks, but it calculates the inLinkRef parameter of that method from inAttributes, inXFA, and inPassedAttrs. If inXFA is not passed in or is empty, it is set to the circuit.fuseaction of the current page.
Chapter 12
Standard Libraries
491
Active4D v5
Batch
If inPassedAttrs is passed in and is not empty, a query string is built from the semicolondelimited list of attributes names, whose values are taken from inAttributes. For the rest of the parameters and examples, see the discussion of makeLinks.
makeLinks
makeLinks(self; ioPrevious; ioBatches; ioNext; inLinkRef {; inCurBatchTag {; inStartParam {; inMaxBatches}}}) Boolean Parameter self ioPrevious ioBatches ioNext inLinkRef inCurBatchTag inStartParam inMaxBatches Result Type Batch Text Text Text Text Text Text Number Boolean
version 4.0
Description The batch object First/previous batch link Batch numbers Next/last batch link The base URL to link to Tag to enclose current batch in Query parameter name for start index Maximum number of batches to display True if links are needed
Discussion This method generates the batch links for all batches that can be generated for the set of rows referred to by self. There are three parts to the links generated: a first/previous batch link, the batch number links, and a next/last batch link. Each is generated separately to give you maximum flexibility in formatting the output. On entry, ioPrevious should contain the encoded HTML text you would like to use for the first/previous batch link. If ioPrevious is empty, the default HTML previous/first batch text is used. If there are no previous batches, an empty string is returned. Otherwise, if the text you pass in ioPrevious contains ^ the text before it is used as the , HTML to display for a first batch link, and the text after it is used as the the HTML to display for a previous batch link. If there is no ^ the text is used for a previous batch , link. If the text for the first batch or previous batch link contains a | (vertical bar), the text before it is the HTML to display, and the text after it is used as the CSS class name for the link. On entry, ioBatches should contain the encoded HTML text you would like to insert between batch numbers, for example If ioBatches is empty, the default HTML . separator is used. If there are batches to display, on return ioBatches will contain HTML with links for each batch that should be displayed. If the text contains a | (vertical bar), the text before it is the text to display, and the text after it is used as the CSS class name for the links.
492
Chapter 12
Standard Libraries
Batch
Active4D v5
The inCurBatchTag parameter determines what HTML tag and CSS class, if any, will be used for the current batch number, which does not have a link. If this parameter contains a | (vertical bar), the text before it is the tag to use (without the enclosing <>), and the text after it is the CSS class name for the tag. If inCurBatchTag is empty, the default tag is used. On entry, ioNext should contain the encoded HTML text you would like to use for the next/last batch link. If ioNext is empty, the default HTML next/last batch text is used. If there are no more batches, an empty string is returned. Otherwise, if the text you pass in ioNext contains ^ the text before it is used as the , HTML to display for a next batch link, and the text after it is used as the the HTML to display for a last batch link. If there is no ^ the text is used for a next batch link. , If the text for the next batch or last batch link contains a | (vertical bar), the text before it is the HTML to display, and the text after it is used as the CSS class name for the link. Note: Be sure to HTML encode the text you pass in ioPrevious, ioBatches, and ioNext. For example, if you would like the previous batch link to say << Previous you , would pass the text << Previous . The inLinkRef parameter should contain the URL that will go in the href of the batch links. If you want to pass query parameters to the destination page, be sure to include them in the query string of this URL. You do not have to (and should not) include the batch start index, that is handled by this method. Note: inLinkRef should be URL encoded. If you want to customize the start index parameter name, pass its name in the inStartParam parameter. If inStartParam is omitted or is empty, the default is used. Note: The standard start index parameter name bst is contained in the library constant Batch.kStartParam. By default this method will generate HTML for all possible batches. If you want to limit the number of batch links that display at one time, pass the maximum number in the inMaxBatches parameter. If inMaxBatches is omitted or is < 0, the default is used. Passing a value of zero means there is no limit on the number of batches generated. If there are more batches than the maximum, batches will be removed from the beginning or end of the list and the current batch will be centered within the list. The result of this method will be True if there is more than one batch, which means you need to display the HTML generated by the method. Example Although it seems complicated, using this method is actually quite easy. Lets take a look at the following scenario:
Chapter 12
Standard Libraries
493
Active4D v5
Batch
3 We have a RowSet with 320 rows, broken up into 32 batches of 10 rows each with no
overlap and a minimum batch size of 2.
3 We want a first batch link of First a previous batch link of «Previous with a ,
CSS class of batch-prev a next batch link of Next» with a CSS class of , batch-next and a last batch link of Next , .
3 We want the current batch number to use a <span> tag with a CSS class of batchcurrent .
3 The target URL will be the current page with a query parameter cid for the company
ID, which we get from the current query params.
3 We will accept the default batch start query parameter of bst . 3 We want to show the default maximum of 7 batches at a time.
Given all of this information, the code to make all this happen is straightforward:
<% $batch := Batch.newFromSelection(->[contacts]; _query) // Set up the HTML c_text($prev; $batches; $next) $prev := "First^«Previous|batch-prev" $next := "Next»|batch-next^Last" $href := requested url + '?cid=_query{"cid"}' $needBatches := $batch->makeLinks($prev; $batches; $next; \\ $href; "span|batch-current") %> <A table with the row data> <% if ($needBatches) %> <p><%=$prev + $batches + $next %></p> <% end if %>
Six lines of code to generate and display the batching is not bad! If you are using Fusebox, assuming your display fuse receives an XFA for the batch links called $XFA_onBatch, you would use the makeFuseboxLinks method like this:
$batch := Batch.newFromSelection(->[contacts]; $attributes) // Set up the HTML c_text($prev; $batches; $next) $needBatches := $batch->makeFuseboxLinks($prev; $batches; \\ $next; $attributes; $XFA_onBatch; "cid"; "span|batch-current")
\\
494
Chapter 12
Standard Libraries
Batch
Active4D v5
new
version 4.0
new(inRowCount; inCollection) Longint new(inRowCount; inSize {; inStart {; inEnd {; inOrphan {; inOverlap}}}}) Longint Parameter inRowCount inCollection OR inRowCount inSize inStart inEnd inOrphan inOverlap Result Type Number Collection Description Row count of data batch is based on Collection from which to get default start index param Row count of data batch is based on Batch size Starting index into the array Ending index into the array Maximum orphans How many rows to overlap Batch object
Discussion This method creates a new batch from row data whose size is inRowCount. For a full discussion of the parameters, see newFromRowSet.
Chapter 12
Standard Libraries
495
Active4D v5
Batch
newFromArray
version 4.0
newFromArray(inArray; inCollection) Longint newFromArray(inArray; inSize {; inStart {; inEnd {; inOrphan {; inOverlap}}}}) Longint Parameter inArray inCollection OR inArray inSize inStart inEnd inOrphan inOverlap Result Type Array Collection Description Data source the batch is based on Collection from which to get default start index param Data source the batch is based on Batch size Starting index into the array Ending index into the array Maximum orphans How many rows to overlap Batch object
Discussion This method creates a new batch from an array of row data contained in inArray. For a full discussion of the parameters, see newFromRowSet.
newFromRowSet
version 4.0
newFromRowSet(inRowSet; inCollection) Longint newFromRowSet(inRowSet; inSize {; inStart {; inEnd {; inOrphan {; inOverlap}}}}) Longint Parameter inRowSet inCollection OR inRowSet inSize inStart inEnd inOrphan inOverlap Result Type RowSet Collection Description Data source the batch is based on Collection from which to get default start index param Data source the batch is based on Batch size Starting index into the array Ending index into the array Maximum orphans How many rows to overlap Batch object
Discussion This method creates a new batch from the RowSet inRowSet.
496
Chapter 12
Standard Libraries
Batch
Active4D v5
There are two forms of this method. The first form receives a collection handle or iterator in the second parameter. The default start index parameter (usually bst) is taken from that collection, and its value is used as the start index. If the parameter is not found, the start index defaults to 1. The rest of the parameters used in the first form are taken from the defaults. In the second form of this method, the number of rows desired in each batch must be passed in the inSize parameter. By default a batch is constructed with a start index of 1 and an end index of inSize. To use a different start index, you can either leave inStart zero and pass a non-zero inSize and inEnd, or leave inSize zero and pass a non-zero inStart and inEnd. If you would like to set the maximum number of orphans (i.e. the minimum batch size) in the last batch, pass a non-zero value in inOrphan. If you would like to overlap one or more rows between batches, pass a non-zero value in inOverlap. Note: For more information on these parameters, see How Batches Are Calculated on page 485. The result of this method is a actually a collection handle that you use with the other methods in the Batch library.
newFromSelection
version 4.0
newFromSelection(inTable; inCollection) Longint newFromSelection(inTable; inSize {; inStart {; inEnd {; inOrphan {; inOverlap}}}}) Longint Parameter inTable inCollection OR inTable inSize inStart inEnd inOrphan inOverlap Result Type Table pointer Collection Description Data source the batch is based on Collection from which to get default start index param Data source the batch is based on Batch size Starting index into the array Ending index into the array Maximum orphans How many rows to overlap Batch object
Discussion This method creates a new batch from a selection of records in the table pointed to by inTable. For a full discussion of the parameters, see newFromRowSet.
Chapter 12
Standard Libraries
497
Active4D v5
Batch
next
next(self; ioLength; ioStart; ioEnd) Boolean Parameter self ioLength ioStart ioEnd Result Type Batch Number Number Number Longint
version 4.0
Description The batch object Batch size Starting index Ending index True if there are more batches
Discussion On entry, ioLength, ioStart and ioEnd should be set to the current values for self. On exit they will be set to the values for the next batch, if any. If there is another batch available, True is returned, else False. Example If you are determined to iterate through batches yourself, you will probably need to use this method like this:
$start := $batch{"start"} $end := $batch{"end"} $length := $batch{"size"} while ($batch->next($length; $start; $end)) // do something end while
previous
previous(self; ioLength; ioStart; ioEnd) Boolean Parameter self ioLength ioStart ioEnd Result Type Batch Number Number Number Longint
version 4.0
Description The batch object Batch size Starting index Ending index True if there are more batches
Discussion On entry, ioLength, ioStart and ioEnd should be set to the current values for self. On exit they will be set to the values for the previous batch, if any.
498
Chapter 12
Standard Libraries
Batch
Active4D v5
setDefaults
setDefaults(inSize; inMinSize; inOverlap; inMaxBatches; inPrevious; inSeparator; inNext; inCurBatchTag; inStartParam) Parameter inSize inMinSize inOverlap inMaxBatches inPrevious inSeparator inNext inCurBatchTag inStartParam Type Number Number Number Number Text Text Text Text Text
version 4.0
Description Receives batch size Receives batch minimum size Receives batch overlap Receives maximum batches to display Receives previous batch HTML Receives batch separator HTML Receives next batch HTML Receives HTML tag for current batch Receives start index parameter name
Discussion This method retrieves the current defaults for all values used by the Batch library. For a discussion of the purpose of each parameter, see Batch Defaults on page 485 and Batch Defaults for Generating Links on page 487.
Chapter 12
Standard Libraries
499
Active4D v5
Breadcrumbs
Breadcrumbs
Very often the data in a dynamic website is structured in a hierarchical fashion, and the user interface follows accordingly. For example, consider the following scenario: 1 2 3 4 5 The user selects a company from a list, which displays a list of departments. The user selects a department, which displays the employees in that department. The user selects an employee, which displays a list of projects the employee is working on. The user selects a project, which displays a list of the work performed on the project by the employee. The user selects a work item, which displays details about the work performed.
At the end of this process the user is five levels deep in the hierarchy. It is essential to provide some context for the user so he or she has some idea how they got to where they are and how to get back to where they came from. The standard technique for doing this is called breadcrumbs The idea is that as users . journey through the site especially if they are descending through a hierarchy you leave a trail of breadcrumbs so that they can find their way back. For example, if you go to www.aparajitaworld.com/store, then roll over the Category menu, and select the category Plugins>Active4D>Deployment Licenses below the , menu strip you will see the following:
Home > Plugins > Active4D > Deployment Licenses
These are the breadcrumbs. Going from left to right, we see the path you took to get to the page you are on. The text between each > is a breadcrumb along the way, and is also a link to jump directly to that point in the path. The Breadcrumbs library gives you a simple interface for building and displaying breadcrumbs. By using this library you will save a lot of code.
Using Breadcrumbs
Using breadcrumbs is basically a three-step process: 1 2 3 Create a breadcrumbs object Add breadcrumbs to the object Write the breadcrumbs on your page
In practice step 2 can be a little complex, because you have to figure out exactly what URL is necessary to retrace your steps. For example, lets consider the following case using Fusebox: 1 From the main page (fuseaction=app.main), the user selects View companies (fuseaction=companies.list).
500
Chapter 12
Standard Libraries
Breadcrumbs
Active4D v5
From the company list, the user selects a company to show the employees for that company (fuseaction=employee.list). The company id is passed in the query param cid . From the employee list, an employee is selected (fuseaction=employees.edit). The employee id is passed in the query param eid .
In a case like this, we can take advantage of the hierarchy of circuits and the fact that Fusebox will call fbx_settings.a4d in each circuit as it descends to the target circuit (employees). So app/fbx_settings.a4d will contain this code:
$breadcrumbs := Breadcrumbs.fuseboxNew("Home"; "app.main")
Now we have a new breadcrumbs object with a home link to the applications main page. Next we descend into the companies circuit. Since a company can be edited (fuseaction=companies.edit), we have to check the fuseaction in app/companies/fbx_settings.a4d:
$breadcrumbs->add("Companies"; "companies.list") if ($fusebox{"isTargetCircuit"}) if ($fusebox{"fuseaction"} = "edit") $breadcrumbs->add("Edit"; "companies.edit"; \\ 'cid=$attributes{"cid"}') end if end if
Finally we descend into the employees circuit. At this point the breadcrumbs are: Home > Companies In app/companies/employees/fbx_settings.a4d we do a check like in the companies circuit, because employees can be listed or edited:
$breadcrumbs->add("Employees"; "employees.list"; 'cid=$attributes{"cid"}') if ($fusebox{"isTargetCircuit"}) if ($fusebox{"fuseaction"} = "edit") $query := a4d.web.collectionItemsToQuery($attributes; \\ "cid;eid") $breadcrumbs->add("Edit"; "employees.edit"; $query) end if end if
Chapter 12
Standard Libraries
501
Active4D v5
Breadcrumbs
When we arrive at the display fuse for the fuseaction employees.edit, the breadcrumbs have been completely built. Now in the app/companies/employees/dsp_editForm.a4d display fuse, we write out the breadcrumbs like so:
<% $breadcrumbs->write %>
The breadcrumbs library takes care of building the whole list, inserting a separator between each breadcrumb, and leaving out a link from the last one (since you are already there).
502
Chapter 12
Standard Libraries
Breadcrumbs
Active4D v5
add
add(self; inText {; inURL {; inQuery}}) Parameter self inText inURL inQuery Type Breadcrumbs Text Text Text
version 4.0
Description The breadcrumbs object Text to display URL/fuseaction for this breadcrumb Query string for this breadcrumb
Discussion This method adds a new breadcrumb to the end of the breadcrumbs list. If self was created with fuseboxNew, inURL should be a fully qualified fuseaction (circuit.fuseaction). Otherwise it should be the URL to target page for the breadcrumb. If you know the breadcrumb is the last one in the chain, you may omit inURL and inQuery. inText is the text that will display when the breadcrumbs are written. It should be URLencoded. inQuery is the query string (if any) to be appended to the target URL. It should be URLencoded, and may be supplied with or without a leading ? .
dumpLib
dump
version 4.0
Discussion This method dumps the library variables used for the default separator and div id.
Chapter 12
Standard Libraries
503
Active4D v5
Breadcrumbs
fuseboxNew
fuseboxNew(inHomeText {; inHomeAction {; inHomeQuery}}) Longint Parameter inHomeText inHomeAction inHomeQuery Result Type Text Text Text Longint
version 4.0
Description Text to display for the home breadcrumb Fuseaction for the home breadcrumb Query string for the home breadcrumb Breadcrumbs object
Discussion This method creates a new breadcrumbs object for use with a Fusebox site and adds a breadcrumb with the values passed in. For more information on the parameters, see add on page 503.
new
new(inHomeText {; inHomeURL {; inHomeQuery}}) Longint Parameter inHomeText inHomeURL inHomeQuery Result Type Text Text Text Longint
version 4.0
Description Text to display for the home breadcrumb URL for the home breadcrumb Query string for the home breadcrumb Breadcrumbs object
Discussion This method creates a new breadcrumbs object for use with non-Fusebox site and adds a breadcrumb with the values passed in. For more information on the parameters, see add on page 503.
504
Chapter 12
Standard Libraries
Breadcrumbs
Active4D v5
setDivId
setDivId(inId) Parameter inId Type Text
version 4.0
Discussion This method sets the id of the div that will wrap breadcrumbs written with all future calls to the Breadcrumbs.write method. For more information on how to use the div id, see Customizing Breadcrumbs Appearance on page 502.
setSeparator
setSeparator(inSeparator) Parameter inSeparator Type Text
version 4.0
Discussion This method sets the HTML that will be inserted between breadcrumbs written with all future calls to the Breadcrumbs.write method. For more information on how to control the appearance of the separator, see Customizing Breadcrumbs Appearance on page 502.
write
write(self ) Parameter self Type Breadcrumbs
version 4.0
Discussion This method writes the breadcrumbs list to the response buffer wrapped in a div. All but the last breadcrumb are links. For more information on how to control the appearance of the breadcrumbs, see Customizing Breadcrumbs Appearance on page 502.
Chapter 12
Standard Libraries
505
Active4D v5
fusebox
fusebox
As software developers, we fight a continual battle to create order out of chaos and to minimize the amount of code we write (at least I do!). Towards this end we make methods, components, and frameworks, so that we might reduce the complexity of our applications, thereby allowing us to focus more clearly on the important problems at hand. Fusebox is a both a framework and a methodology that fulfills this promise. To describe it I will quote from the fusebox.org web site.
An Overview of Fusebox
Application developers face a daunting task: they must translate the often fuzzilydefined requirements for a new application into the rigid language of computers. While the Fusebox Lifecycle Process (FLiP) offers help in managing the project management aspects of creating a new application, what help is there available to developers approaching the technical challenges of creating and maintaining applications? Application frameworks answer this question, offering pre-built (and pre-tested) code a collection of services that can provide the architectural underpinnings for a particular type of application. As web development matures, web-based application frameworks allow the developer to concentrate more on meeting the business needs of the application and less on the plumbing needed to make that application work. Fusebox is, by far, the most popular and mature web framework available for ColdFusion and PHP developers [and now for Active4D developers!]. The architecture of a Fusebox application is divided into various sections (circuits in Fusebox parlance), each of which has a particular focus. For example, the responsiblity for ensuring that only authorized users have access to all or part of the application might fall under a Security circuit. The Fusebox application architect defines these circuits, as well as the individual actions (fuseactions) that may be requested of it. When a fuseaction request is made of the application, the Fusebox machinery (the Fusebox) routes the request to the appropriate circuit, where the fuseaction is processed. This idea of encapsulation of responsibilities makes it easy for different functional circuits to be plugged into an application, making it possible to reuse code. Within the individual circuit responsible for carrying out the requested fuseaction, the Fusebox architect specifies the individual files (fuses) needed to fulfill the fuseaction request. Thus, the Fusebox acts like a good manager, delegating tasks to appropriate departments where it is decomposed into individual tasks, each of which can be assigned to individuals to carry out.
3 It doesnt just promise to make web development easier, it actually fulfills that
promise. With Fusebox you will write less code with less bugs that is easier to maintain.
506
Chapter 12
Standard Libraries
fusebox
Active4D v5
3 The guys who designed Fusebox are incredibly smart and have a lot of experience
writing web applications. The chances are what they have come up with is a lot better than any sort of framework we could design.
3 Last but certainly not least, Fusebox is the programming model of choice for Active4D.
All demos and sample code are in Fusebox.
3 Syntax differences: Where ColdFusion talks about structures, Active4D will use
collections. When you see a ColdFusion structure reference like Fusebox.circuit, the Active4D equivalent is $fusebox{"circuit"}.
Chapter 12
Standard Libraries
507
Active4D v5
fusebox
Description When set to false by a circuit, prevents its layouts from being nested in parent circuit layouts contains the name of the single point of entry into fusebox, usually index.a4d .
Configuring Fusebox
By default the name of the fuseaction query parameter is fuseaction In actual fact this . name is not hard-coded into the fusebox library, but is defined as the library constant fuseaction in the fusebox.conf library. If you would like to change the fuseaction query parameter name, you can do so by changing the define in the fusebox.conf. If you want to refer to the fully qualified circuit.fuseaction within your fuses, you should always do so in this way:
$fuseaction := $fusebox{fusebox.conf.fuseaction}
508
Chapter 12
Standard Libraries
fusebox
Active4D v5
core
core(inRootPath {; ioAttributes {; inNestedCall}}) Parameter inRootPath ioAttributes inNestedCall Type Text Collection Boolean
Description Path to the directory of index.a4d The request context True if called from sendFuseaction
Discussion This method is the Active4D Fusebox core file. You should never have to call this method directly.
getURLFactory
getURLFactory Text Parameter Result Type Text
version 4.5
Discussion This method returns the name of the method which will be called to create URLs when fusebox.makeURL is called. For more information on URL factory methods, see setURLFactory on page 512.
handleError
handleError(inTarget {; inQuery}) Parameter inTarget inQuery Type Text Text
version 4.0
Description The fully qualified circuit.fuseaction to call, or a full URL+query to redirect to Query string
Discussion This method is meant to be called from the error page configured in Active4D.ini, or the error page set by a call to set error page.
Chapter 12
Standard Libraries
509
Active4D v5
fusebox
If inTarget begins with / it is considered to be a full URL + query string (it should be URL, encoded) to redirect to. Otherwise it is considered to be a fully qualified circuit.fuseaction, which will be passed along with inQuery to fusebox.makeURL to construct the URL to redirect to. If inQuery is passed, it should already be URL-encoded. Before redirecting to the target URL, the standard $a4d_err_x error variables are put in the session as session{"a4d_err_x"}. In addition, the full requested URL and referer are put in the session as a4d_err_url and a4d_err_referer respectively. To ensure proper cleanup, the target fuseaction should call fusebox.postHandleError after using the session items created by this method. For a discussion of how to handle errors in Fusebox, see Custom Error Handling in Fusebox on page 564.
isFuseboxRequest
isFuseboxRequest Boolean Parameter Result Type Boolean Description Query string
version 4.0
Discussion This method returns True if the current request is being handled by Fusebox, False if not.
makeURL
makeURL(inFuseaction {; inQuery}) Text Parameter inFuseaction inQuery Result Type Text Text Text
Description The fully qualified circuit.fuseaction to call Query string URL suitable for use with Fusebox
Discussion This method creates a Fusebox URL suitable for use with links, form actions, redirects, etc. If inQuery is passed, it should already be URL-encoded. If a URL factory method has been set with fusebox.setURLFactory, that method will be called with the arguments inFuseaction and inQuery.
510
Chapter 12
Standard Libraries
fusebox
Active4D v5
postHandleError
postHandleError
version 4.0
Discussion This method should be called from the target fuseaction of the fusebox.handleError method, after the session items created by fusebox.handleError are used.
sendFuseaction
sendFuseaction(self; inFuseaction {; ioAttributes}) Parameter self inFuseaction ioAttributes Type Collection Text Collection
Description The $fusebox collection The fully qualified circuit.fuseaction to call The request context
Discussion When you want to call a fuseaction within the fuse of another fuseaction, use this method. Typically you would call it like this:
// Insert a calendar, pass today's date in the attributes $attrs := new collection("date"; \\ string(current date; MM DD YYYY Forced)) $fusebox->sendFuseaction("calendar.view"; $attrs)
ioAttributes should contain the same items that can validly be passed to the target fuseaction either through a query string or through form variables. Because the new fuseaction is running within a method call, you will not have access to any of the local variables used within the calling fuseaction. To pass values to the nested fuseaction, use ioAttributes or the built in _request collection.
Chapter 12
Standard Libraries
511
Active4D v5
fusebox
setURLFactory
setURLFactory(inMethod) Text Parameter inMethod Result Type Text Text
version 4.5
Description The method to delegate URL creation to Previous URL factory method
Discussion If you want to use your own URL style, use this method to set the name of a method which will be called to create URLs when fusebox.makeURL is called. Your factory method should take the same parameters as fusebox.makeURL and return the full URL. If inMethod is empty, the default URL form is used. The previous URL factory method is returned. Example Lets assume that instead of the default URL form:
/index.a4d?action=<circuit>.<action>;<query>
We have a makeUrl method in a library called mylib which can create URLs in the new form. The method looks like this:
method "makeUrl"($inFuseaction; $inQuery = "") $circuit := slice string($inFuseaction; "."; $action) $url := "/%s/%s" % ($circuit; $action) if (length($inQuery) > 0) $url += "?" + $inQuery end if return ($url) end method
We can easily use our new URL style without changing all of our calls to fusebox.makeURL by setting a custom URL factory method. In this case we would call the following code in the On Application Start method of the Active4D library:
fusebox.setURLFactory("mylib.makeUrl")
512
Chapter 12
Standard Libraries
fusebox
Active4D v5
Chapter 12
Standard Libraries
513
Active4D v5
fusebox.head
fusebox.head
A Fusebox application is made up of many different circuits that work together. The Fusebox methodology (and good programming practice) demands that these circuits be as independent as possible. Ideally they should know nothing about each other. In addition, Fusebox also tries to separate the presentation of a site from the logic by using layouts. These layouts typically are responsible for writing the HTML header in a page. And like the circuits, the layouts should know little or nothing about the rest of the application. But what happens if the circuits need to write things into the HTML header, such as meta tags, stylesheet includes, Javascript includes, etc. How can we allow circuits to write to the header without the header knowing about them? This library facilitates the decoupling of circuits and layouts by providing a means for registering information that should go in the HTML header. The layouts can then use a method in this library to write that info without knowing anything about the circuits themselves.
Because you are adding header elements in fbx_settings.a4d, they are added from the most generic to the most specific as Fusebox traverses from the root circuit to the target circuit. Note: This library creates items in the _request collection whose keys begin with fusebox.head. Be sure not to use such keys yourself for any _request items. .
514
Chapter 12
Standard Libraries
fusebox.head
Active4D v5
addCSS
addCSS(inFusebox; inURLs) Parameter inFusebox inURLs Type Collection Text
version 4.0
Discussion This method adds one or more URLs that will go into the href attribute of a <link> tag to load a CSS stylesheet. To pass more than one URL, concatenate them together with semicolons. The URLs will be URL-encoded for you. If the URL of a stylesheet is a relative path, it is assumed it is relative to the directory of the current circuit. This makes it much easier for you to specify circuit-relative paths. If you want to use a path which is relative to the Fusebox root, you should do something like this:
$path := join paths($fusebox{"rootPath"}; "path/to/styles.css")
If you want the stylesheets to apply to a given media, prefix the filename of the stylesheet with @ followed by the media type. , If you want a stylesheet to be an alternate stylesheet, add the alternate stylesheet title after the filename, separated by a colon. If you want to pass verbatim text, pass ! followed by the text. If you want to add attributes to the link tag which is generated, append | followed by the attributes (and values if necessary) to the filename. Examples Let us assume a calendar circuit needs to have access to a stylesheet calendar.css that is within a css directory within the circuit directory. To add this stylesheet to the header, we would execute the following code in the fbx_settings.a4d of the calendar circuit:
fusebox.head.addCSS($fusebox; "css/calendar.css")
If more than one path needs to be added, we can concatenate them together using the concat command:
fusebox.head.addCSS($fusebox; concat(";"; \\ "css/calendar.css"; \\ "css/@screen:calendar_small.css:small text"; \\ "css/@screen:calendar_large.css:large text"; \\ "css/@print:calendar_print.css"; \\ "css/event.css"))
Chapter 12
Standard Libraries
515
Active4D v5
fusebox.head
Note in the above example that calendar_small.css and calendar_large.css are screen media alternate stylesheets with the title small text and large text respectively. The stylesheet calendar_print.css will only be used when printing. Assuming the path from the web root to the calendar circuit is portlets/calendar, a call to fusebox.head.write will result in the following comments and tags being written:
<!-- css added by calendar circuit -> <link rel="stylesheet" type="text/css" href="/portlets/calendar/css/calendar.css" /> <link rel="alternate stylesheet" type="text/css" href="/portlets/calendar/css/calendar_small.css" media="screen" title="small text" /> <link rel="alternate stylesheet" type="text/css" href="/portlets/calendar/css/calendar_large.css" media="screen" title="large text" /> <link rel="stylesheet" type="text/css" href="/portlets/calendar/css/calendar_print.css" media="print"/> <link rel="stylesheet" type="text/css" href="/portlets/calendar/css/event.css" /> <!-- end calendar circuit css -->
Now lets suppose we have to create a specialized stylesheet for IE6 to get around its bugs. We can do that by using a conditional stylesheet include, like this:
fusebox.head.addCSS(concat(";"; \\ "!<!--[if lt IE 7]>"; \\ "/css/ie6.css"; \\ "!<![endif]-->"))
addDumpStyles
addDumpStyles
version 4.0
Discussion This method sets a flag which will cause the method a4d.debug.writeDumpStyles to be called when fusebox.head.write is called.
516
Chapter 12
Standard Libraries
fusebox.head
Active4D v5
Normally you do not need to call this method, it is called by the methods in the a4d.debug libary. If you plan to use the Active4D dump styles in a fusebox application, use this method, since the styles get written to the page header where they belong.
addJavascript
addJavascript(inFusebox; inURLs) Parameter inFusebox inURLs Type Collection Text
version 4.0
addJS
addJS(inFusebox; inURLs) Parameter inFusebox inURLs Type Collection Text
version 4.0
Discussion This method adds one or more URLs that will go into the src attribute of a <script> tag to load a Javascript file. To pass more than one URL, concatenate them together with semicolons. The URLs will be URL-encoded for you. If the URL of a Javascript file is a relative path, it is assumed it is relative to the directory of the current circuit. This makes it much easier for you to specify circuit-relative paths. If you want to use a path which is relative to the absolute web root, begin the path with / . If the Fusebox root (where index.a4d is located) is within a subdirectory of the web root, you have to build the path to the Javascript file like this:
$path := join paths($fusebox{"rootPath"}; "path/to/script.js")
If you want to pass verbatim text, pass ! followed by the text. If you want to add attributes to the script tag which is generated, append | followed by the attributes (and values if necessary) to the filename.
Chapter 12
Standard Libraries
517
Active4D v5
fusebox.head
Example Let us assume a calendar circuit needs to have access to a Javascript file calendar.js that is within a js directory within the circuit directory. To load this Javascript file in the header, we would execute the following code in the fbx_settings.a4d of the calendar circuit:
fusebox.head.addJS($fusebox; "js/calendar.js")
If more than one path needs to be added, we can concatenate them together like this:
fusebox.head.addJS($fusebox; \\ concat(";"; "js/calendar.js"; "js/events.js"; "/js/help.js"))
Assuming the path from the web root to the calendar circuit is portlets/calendar, a call to fusebox.head.write will result in the following tags being written:
<!-- Javascript added by calendar circuit --> <script type="text/javascript" src="/portlets/calendar/js/calendar.js"> </script> <script type="text/javascript" src="/portlets/calendar/js/event.js"> </script> <script type="text/javascript" src="/js/event.js"></script> <!-- end calendar circuit Javascript -->
Now lets suppose we have to include a Javascript file only on IE6 to enable it to display PNG images with transparency. In addition, we have to add the defer attribute to the script tag, because the file must not executed when it is loaded. We can accomplish this by using a conditional include, like this:
fusebox.head.addJS(concat(";"; \\ "!<!--[if lt IE 7]>"; \\ "/js/pngfix.js|defer"; \\ "!<![endif]-->"))
Note we added the defer attribute by appending |defer to the file path.
518
Chapter 12
Standard Libraries
fusebox.head
Active4D v5
addMetaTag
addMetaTag(inFusebox; inTags) Parameter inFusebox inTags Type Collection Text
version 4.0
Discussion This method adds one or more <meta> tags to the header. Only the content of the meta tag should be passed, not the meta tag itself. To pass more than one meta tag, concatenate them together with vertical bars (|). The meta tag content will not be URL encoded for you, it must be URL encoded by you if necessary. Example When a new user comes to the site, we redirect to a checker circuit which determines which browser is being used, as well as if Javascript and cookies are enabled. In order to do the cookie and Javascript checking, the circuit needs to put a meta refresh tag in the header:
$url := "http://" + join paths(request info{"host"}; \\ fusebox.makeURL("checker.checkJS") $tag := 'http-equiv="refresh" content="1;URL=$url"' fusebox.head.addMetaTag($fusebox; $tag)
If our current host is my.host.com and fusebox.conf.fuseaction is action a call to , fusebox.head.write will result in the following tag being written:
<!-- meta tags added by checker circuit --> <meta http-equiv="refresh" content="1;URL=http://my.host.com/index.a4d?action=checker.JS" /> <!-- end checker circuit meta tags -->
getTitle
getTitle Parameter inTitle Type Text Description Window title
version 4.0
Discussion This method sets the title of the window, which will be written out as the <title> tag when fusebox.head.write is called. The text will be HTML encoded when it is written, you should not encode it yourself.
Chapter 12
Standard Libraries
519
Active4D v5
fusebox.head
setTitle
setTitle(inTitle) Parameter inTitle Type Text Description Window title
version 4.0
Discussion This method sets the title of the window, which will be written out as the <title> tag when fusebox.head.write is called. The text will be HTML encoded when it is written, you should not encode it yourself. In a Fusebox application, you should call this method in the root circuits fbx_settings.a4d, then you can specialize the title in other circuits by calling it in other circuits fbx_settings.a4d or display fuses. The call closest to the target circuit will ultimately set the title.
write
write
version 4.0
Discussion This method writes the tags specified by the add<type> methods and the setTitle method. When writing the tags, they are separated by circuit and their source is noted in HTML comments to aid in debugging your code.
520
Chapter 12
Standard Libraries
RowSet
Active4D v5
RowSet
In the course of building a dynamic, database-driven web site, one of the most common tasks is to perform a query and then display or edit the results of that query. Such actions always have the following attributes:
3 The result of the query is an ordered set of one or more rows in the database. 3 Each row consists of one or more columns. 3 To display the set of rows you must iterate over each row in order. 3 To display a single row you must access the column data for that row. 3 The data source of the column data typically consists of fields within a selection of
records or elements within an array.
3 Simple syntax for working with rows 3 Uniform API no matter what the source of the row data is 3 Ability to use dummy data if real table data is not available 3 You can embed complex queries and data manipulations into the RowSet
specification, much like a SQL query At the heart of a RowSet is the data source. The data source acts as the conduit between the actual row data and the RowSet API. Currently there are three possible data sources for a RowSet:
3 When you create a RowSet, you map virtual column names to the data source
columns.
3 You can access RowSet data by index, with the order being determined by the order in
which you declare the columns in the mapping.
Chapter 12
Standard Libraries
521
Active4D v5
RowSet
This architecture means that changes to the underlying data source will affect only the one or two lines of code where you create the RowSet and declare the column/data mapping. For example, lets say that you want to display a list of people. The list will have the following columns:
In this case the logical column names happen to correspond to the physical field names in the structure. But what happens if the structure changes (as it often does)? For example, lets say that the [People]Name field is renamed to [People]FullName, new phone number and email address fields are added, and the original fields are renamed, such that the data source for our name phone and email columns now are: ,
All of the rest of the code that uses the RowSet will remain unaffected. Okay, you say, that's fine, but I don't see what the big deal is. I still have to change the field names in all of my mappings. While this is true, insulation from structure changes is not the only benefit you get from RowSets.
522
Chapter 12
Standard Libraries
RowSet
Active4D v5
Lets suppose that at some point you decide not to access the selection directly, but for one reason or another you fetch (or build) the data into these arrays:
None of the code that works with the RowSet will have to change! But it gets better. When you are developing your web site, you may not have access to the database, either because it has not yet been finalized or because you are working remotely. In that case you want to have some sample data so you can test your code, but where do you get it from? With RowSets it is easy. You can create a RowSet from delimited text data, which could be read in from a file. To use this as your data source instead of selections or arrays, you need only change the RowSet creation code, like this:
$rs := RowSet.newFromData($myData)
Again, none of the code that uses the RowSet will have to change.
Using RowSets
Once you have created a RowSet, to iterate through its rows you simply do this:
while ($rs->next) // Show data end while // sometimes a for loop is preferable for ($i; $rs->getStart; $rs->getEnd) $rs->gotoRow($i) // Show data end for
Chapter 12
Standard Libraries
523
Active4D v5
RowSet
How you choose to display the row data is up to you. You have three ways of accessing column within a row:
3 By getting the row data collection with getRow and indexing that by column name 3 By column index using getData 3 By column name using getData
Of the three techniques, the first is recommended, because it results in clearer (and faster) code. Here is an example of the first technique:
<% $row := $rs->getRow while ($rs->next) %> <tr> <td><% =$row{"name"} %></td> <td><% =$row{"phone"} %></td> <td><% =$row{"email"} %></td> </tr> <% end while %>
This is by far the simplest technique. However, there may be times when you are programmatically creating columns and it is easier to iterate through the columns by index, like this:
<% $numColumns := $rs->columnCount while ($rs->next) %> <tr> <% for ($i; 1; $numColumns) %> <td><% =$rs->getData($i) %></td> <% end for %> </tr> <% end while %>
You may not like using indexes, since you cant see what column you are using without referring to the column mapping, so you can use column names instead. Heres an example of using column names to access column data:
<% while ($rs->next) %> <tr> <td><% =$rs->getData("name") %></td> <td><% =$rs->getData("phone") %></td> <td><% =$rs->getData("email") %></td> </tr> <% end while %>
524
Chapter 12
Standard Libraries
RowSet
Active4D v5
Thats about all there is to iterating through and accessing row data in a RowSet. Its about as easy as it can get. And rememberyou can change your data source and none of your iterating code will have to change!
3 Pass a Batch when creating the RowSet. The Batch start and end indexes will become
the start and end rows of the RowSet.
3 Pass the start and end indexes as a delimited pair in the form "<start>:<end>".
For more information on using row subsets, see the newFrom<Source> method descriptions below.
RowSet Cursors
Every RowSet has a cursor which keeps track of the current row. Unlike 4D query commands which automatically go to the first record in a selection, when a RowSet is first created the cursor is before the first row of the RowSet. Like the current record in a selection, the cursor can be in one of three states:
3 before first: This corresponds to Before selection in 4D. This is the state you
ordinarily start in when iterating forward through a RowSet.
3 within: The cursor index is within the range 1 to the number of rows in the RowSet if
the RowSet has been created with the entire set of source data. If the RowSet represents a subset of the source data, the cursor index is within the range <subrange start> to <subrange end> inclusive.
3 after last: This corresponds to End selection in 4D. This is the state you ordinarily
start in when iterating backward through a RowSet. There is a full suite of methods that allow you to move the cursor and determine its current state.
Persistent RowSets
There is a certain amount of overhead involved in creating a RowSet. For data sets that change infrequently or not at all, it would be nice if you could avoid the overhead of creating a new RowSet on every request.
Chapter 12
Standard Libraries
525
Active4D v5
RowSet
By passing a name to one of the newFrom<Source> methods, you create a persistent RowSet: one that remains in memory until you specifically clear or overwrite it. Once a persistent RowSet is created, you can access it by name in subsequent requests. In addition, because you can set a timeout for a RowSet, you can easily implement a refresh interval. For example, lets say you want to create a persistent RowSet for a list of product categories, since they change very infrequently, and you would like the RowSet to timeout every 8 hours. You would do something like this:
all records([categories]) order by([categories]; [categories]name) $map := """ id: [categories]id; name: [categories]name""" $qryCategories := RowSet.newFromSelection(->[categories]; \\ $map; -1; ""; "categories"; 60 * 8)
By passing a name as the next to last parameter when creating a RowSet, you make that RowSet persistent. The number after the name is the RowSet timeout in minutes. To retrieve a persistent RowSet, you simply do this:
$qryCategories := RowSet.persistent("categories")
If the given persistent RowSet does not exist, zero is returned. To see if a RowSet has timed out, you do this:
if ($qryCategories->timedOut)
Putting it all together, your code to create a persistent RowSet will follow this sort of pattern:
$qryCategories := RowSet.persistent("categories") if ($qryCategories # 0) if (not($qryCategories->timedOut)) return end if end if all records([categories]) order by([categories]; [categories]name) $map := """ id: [categories]id; name: [categories]name""" $qryCategories := RowSet.newFromSelection(->[categories]; \\ $map; -1; ""; "categories"; 60 * 8)
526
Chapter 12
Standard Libraries
RowSet
Active4D v5
3 Data comes from the database: If the source of your data is the database, use
newFromSelection or newFromCachedSelection. Using row callbacks and column expressions, you can do very sophisticated queries and data manipulations with very little work. If you need to search in a RowSet or iterate through its rows more than once, consider using newFromCachedSelection. If you need to use a cached selection and one or more columns must be calculated, consider using SELECTION TO ARRAY to load the non-calculated columns and then using setColumnArray to add the calculated columns. If you need to directly access a blob field, you must use newFromSelection, since all of the other RowSets are array-based, and there are no blob arrays in 4D. To get around this you can use a column expression that extracts the data you need from the blob, in which case newFromCachedSelection can be used.
3 Data comes from arrays: If you need to build arrays through complex queries and
manipulations of the data, consider using newFromCachedSelection with a row callback and column expressions. Usually that can accomplish what you need but it does most of the work for you. If you just need to create a RowSet with one or more calculated columns, you can load the non-calculated columns using SELECTION TO ARRAY and then use setColumnArray to add the calculated columns. For more information on this strategy, see setColumnArray on page 547. If the ultimate source of your data is arrays, obviously you must use newFromArrays.
Chapter 12
Standard Libraries
527
Active4D v5
RowSet
afterLast
afterLast(self ) Parameter self Type RowSet Description RowSet reference
version 3
Discussion This method moves the cursor of self to just after the last row in the RowSet. After this call isAfterLast will return True and previous will move to the last row if there is one.
beforeFirst
beforeFirst(self ) Parameter self Type RowSet Description RowSet reference
version 3
Discussion This method moves the cursor of self to just before the first row in the RowSet. After this call isBeforeFirst will return True and next will move to the first row if there is one.
clearPersistent
clearPersistent(inName) Parameter inName Type Text
version 4.0
Discussion This method does a deep clear of the persistent RowSet named inName and removes it from the list of persistent RowSets. If no such RowSet exists, nothing happens.
528
Chapter 12
Standard Libraries
RowSet
Active4D v5
columnCount
columnCount(self ) Longint Parameter self Result Type RowSet Longint
version 3
Discussion This method returns the number of columns in a RowSet. Use this as the end index when iterating over the RowSet columns.
currentRow
currentRow(self ) Longint Parameter self Result Type RowSet Longint Description RowSet reference Current row of RowSet
version 3
Discussion This method returns the current position of the cursor of self. If isBeforeFirst is True, this method returns RowSet.kRow_BeforeFirst. If isAfterLast is True, this method returns getEnd + 1.
dumpPersistent
dumpPersistent
version 4.0
Discussion This method writes a nicely formatted dump listing the name, number of rows, and column names for each persistent RowSet.
Chapter 12
Standard Libraries
529
Active4D v5
RowSet
dump
dump(self {; inName {; inShowType}}) Parameter self inName inShowType Type RowSet Text Boolean
version 4.0
Discussion This method writes a nicely formatted dump of all columns and rows in self to the output buffer. This is very useful for debugging your queries, row callbacks and column maps.
findColumn
findColumn(self; inColumn) Longint Parameter self inColumn Result Type RowSet Text Longint Description RowSet reference Column name to find Index of column
version 3
Discussion This method returns the index of a column given a name. Columns are indexed in the order they were declared on RowSet creation. If no column with the given name exists, zero is returned.
findRow
findRow(self; inColumn; inValue) Longint Parameter self inColumn inValue Result Type RowSet Text <any> Longint
version 3
Description RowSet reference Column in which to search Value to search for Index of first matching row
Discussion This method performs a linear search of the column inColumn for the value inValue, starting at the first row of self. If a match is found, the index of the first matching row is
530
Chapter 12
Standard Libraries
RowSet
Active4D v5
returned and the cursor is moved to that row. If a match is not found, zero is returned and isAfterLast is True. The type of inValue must be assignment compatible with the type of the column referenced by inColumn. Note: If the RowSet was created with newFromSelection with no subset of source rows specified, the search may be very slow, because each record in the selection is loaded one by one starting from the first record of the selection. If you need to use this method with a selection-based RowSet, be sure to create the RowSet with a subset of source rows, or use a cached RowSet.
first
first(self ) Boolean Parameter self Result Type RowSet Boolean Description RowSet reference True if there is a first row
version 3
Discussion This method moves the cursor to the first row of self. If there is a first row (rowCount > 0), True is returned, else False.
getColumn
getColumn(self; inIndex) Text Parameter self inIndex Result Type RowSet Number Text Description RowSet reference Column index Column name
version 3
Discussion This method returns the name of the column with the given index. Columns are indexed in the order they were declared on RowSet creation. If no column with the given index exists, an error is thrown.
Chapter 12
Standard Libraries
531
Active4D v5
RowSet
getData
getData(self; inColumn) <any> Parameter self inColumn Result Type RowSet Number/Text <any> Description RowSet reference Column index/name Column data
version 3
Discussion This method retrieves data from the column inColumn in the current row of self. If inColumn is a number, it is taken as a column index. Columns are indexed in the order they were declared on RowSet creation. If inColumn is a string or text, it is taken as a column name. If inColumn is not a valid column index or name, an error is thrown. If inColumn is valid and there are no rows in the RowSet, or isBeforeFirst or isAfterLast is True, an empty value for the columns type is returned.
getEnd
getEnd(self ) Longint Parameter self Result Type RowSet Longint Description RowSet reference Last row of RowSet
version 4.0
Discussion This method returns the number of the last row in self.
getPersistentList
getPersistentList(outList) Parameter outList Type String/Text Array
version 3
Discussion This method retrieves a list of the persistent RowSet names into outList. If outList is not a String/Text Array, an error is generated and execution is aborted.
532
Chapter 12
Standard Libraries
RowSet
Active4D v5
getRow
getRow(self ) Longint Parameter self Result Type RowSet Collection Description RowSet reference Row data
version 3
Discussion This method returns a reference to a collection which contains all of the row data for the current row of self. The data in the collection is keyed on the column name. This is the easiest and most efficient way to access row data. See Using RowSets on page 523 for an example of using this method to access row data.
getStart
getStart(self ) Longint Parameter self Result Type RowSet Longint Description RowSet reference First row of RowSet
version 4.0
Discussion This method returns the number of the first row in self.
getTimeout
getTimeout(self ) Number Parameter self Result Type RowSet Number Description RowSet reference Timeout in minutes
version 3
Chapter 12
Standard Libraries
533
Active4D v5
RowSet
gotoRow
gotoRow(self; inRow) Boolean Parameter self inRow Result Type RowSet Number Boolean Description RowSet reference Row number True if a valid row
version 3
Discussion This method moves the cursor to a given row within self. If inRow is positive, the cursor is moved to the absolute row number given. If inRow is negative, the cursor is positioned relative to the end of the RowSet. A value of -1 positions the cursor on the last row, -2 on the second to last row, and so on. If inRow > rowCount, this method effectively performs afterLast. If inRow is negative and abs(inRow) > rowCount, this method effectively performs beforeFirst.
isAfterLast
isAfterLast(self ) Boolean Parameter self Result Type RowSet Boolean
version 3
Discussion This method returns True if the cursor is positioned after the last row of self or if there are no rows in self.
534
Chapter 12
Standard Libraries
RowSet
Active4D v5
isBeforeFirst
isBeforeFirst(self ) Boolean Parameter self Result Type RowSet Boolean
version 3
Discussion This method returns True if the cursor is positioned before the first row of self or if there are no rows in self.
isFirst
isFirst(self ) Boolean Parameter self Result Type RowSet Boolean Description RowSet reference True if current row is first
version 3
Discussion This method returns True if the cursor is positioned at the first row of self.
isLast
isLast(self ) Boolean Parameter self Result Type RowSet Boolean Description RowSet reference True if current row is last
version 3
Discussion This method returns True if the cursor is positioned at the last row of self.
Chapter 12
Standard Libraries
535
Active4D v5
RowSet
last
last(self ) Boolean Parameter self Result Type RowSet Boolean Description RowSet reference True if there is a last row
version 3
Discussion This method moves the cursor to the last row of self. If there is a last row (rowCount > 0), True is returned, else False.
maxRows
maxRows(self ) Longint Parameter self Result Type RowSet Longint Description RowSet reference Maximum rows in RowSet
version 3
Discussion This method returns the maximum rows in self, as set by the inSubset parameter during RowSet creation. If there is no limit on the number of rows, -1 is returned. Note that maxRows > rowCount is possible if the number of rows in the data source was less than inSubset at the time of RowSet creation.
move
move(self; inRows) Boolean Parameter self inRows Result Type RowSet Number Boolean
version 3
Description RowSet reference Number of rows to move True if moving to a valid row
Discussion This method moves the cursor relative to the current row of self by the number of rows given in inRows.
536
Chapter 12
Standard Libraries
RowSet
Active4D v5
If currentRow + inRows is in the range 1..rowCount, True is returned. If inRows is positive and currentRow + inRows > rowCount, this method effectively performs afterLast. If inRows is negative and currentRow + inRows < 1, this method effectively performs beforeFirst. In either case False is returned.
newFromArrays
Discussion This method creates a RowSet from a group of arrays. The columns in the RowSet are determined by inColumnMap, which maps virtual column names to array references, which can be any valid Active4D array reference, which includes local arrays, process/interprocess arrays, and arrays within collections. The column map is formatted as a semicolon-delimited list of column:array pairs. Whitespace before and after the column name and array reference is ignored. For example, the following code would create a four-column RowSet:
global($ids; $names; $birthdays; $genders) selection to array([contacts]id; $ids; \\ [contacts]name; $names; \\ [contacts]birthdate; $birthdays; \\ [contacts]gender; $genders) $map := """ id: $ids; name: $names; birthdate:$birthdays; gender: $genders""" $rs := RowSet.newFromArrays($map)
One important thing to note in the example above is the global declaration of the arrays before they are created. For newFromArrays to do its magic, it must have access to any local variables that are used as array references in the column map. So any local variables used within a column map must be declared global before they are created or used.
Chapter 12
Standard Libraries
537
Active4D v5
RowSet
Note also that $ids and the other local arrays in the above example could just as easily be session items, process arrays or interprocess arrays. In that case the global declaration is of course unnecessary. If you need to reference an array within a collection which is local, you must declare the collection itself as global. Here is another example where the session is storing a shopping cart in the parallel arrays session{"cart.qtys"}, session{"cart.descriptions"} and session{"cart.prices"}. To create a RowSet from the shopping cart is simple:
$map := """ qty: session{"cart.qtys"}; description: session{"cart.descriptions"}; price: session{"cart.prices"}""" $rs := RowSet.newFromArrays($map)
If all of the arrays in the column map are not the same size, the copies within the RowSet are padded to the length of the first one or the specified subset of rows, whichever is less. For a discussion of the remaining parameters, see newFromSelection on page 541.
newFromCachedSelection
version 4.0
newFromCachedSelection(inMainTable; inColumnMap {; inSubset {; inRowCallback {; inName {; inTimeout}}}}) Longint Parameter inMainTable inColumnMap inSubset inRowCallback inName inTimeout Result Type Table pointer Text Number/Batch/Text Text Text Number RowSet Description Pointer to main table Virtual column mapping Maximum rows/subset of rows Code to execute when loading a row Persistent name Timeout in minutes RowSet object
Discussion This method creates a RowSet in exactly the same way as newFromSelection, but all of the data is preloaded into memory when the RowSet is created. For a full discussion of the parameters, see newFromSelection on page 541. Reasons why you might use this method instead of newFromSelection include:
3 You need to manipulate inMainTables selection after creating the RowSet but before it
is displayed.
3 You need to use the RowSet find method to search within the RowSet. 3 A cached RowSet sounds a lot cooler than one that isnt.
538
Chapter 12
Standard Libraries
RowSet
Active4D v5
For a discussion of the performance considerations of using cached vs. non-cached RowSets, see To Cache or Not to Cache? on page 545.
newFromData
newFromData(inData {; inRowDelimiter {; inColumnDelimiter {; inSubset {; inName {; inTimeout {; inTextFormat}}}}}}) Longint Parameter inData inRowDelimiter inColumnDelimiter inSubset inName inTimeout inTextFormat Result Type Text/BLOB Text Text Number/Batch/Text Text Number Number RowSet
version 4.0
Description Delimited data Delimiter between rows Delimiter between columns Maximum rows/row subset Persistent name Timeout in minutes Storage format of text RowSet object
Discussion This method creates a RowSet from delimited data, such as CSV (comma separated values), coming from a text or BLOB variable. The first row of inData contains column names, followed by one or more data rows, with each row delimited by inRowDelimiter and each column delimited byinColumnDelimiter. Whitespace around the column names is trimmed. If inColumnDelimiter is not passed, it defaults to , If inRowDelimiter is not passed, it . defaults to line feed (\n). Only the first character of each is used. If a columns data might contain the column delimiter, you should enclose the column data in double quotes. The quotes are not included as part of the column data. To specify a column data type, append one of the following types to the name, separated by a colon:
Chapter 12
Standard Libraries
539
Active4D v5
RowSet
In the case of the string type, the number in parentheses specifies the string width. Note: The string type in v5 is identical to the text type and has been kept for backwards compatibility. The maximum size of the column info plus the data is 2GB. Note that unlike the other RowSet types, if a subset of rows is specified, sourceRowCount will return the same as getEnd, because scanning of the source data is aborted as soon as the last specified row is reached. Also, row 1 is considered the first row after the header row. If inTextFormat is passed and inData is a BLOB, it represents the storage format of the text within the BLOB. If it is not passed, the format defaults to Mac Text without length for backwards compatibility. For a discussion of the remaining parameters, see newFromSelection on page 541.
newFromFile
newFromFile(inPath {; inRowDelimiter {; inColumnDelimiter {; inSubset {; inName {; inTimeout {; inTextFormat}}}}}}) Longint Parameter inPath inRowDelimiter inColumnDelimiter inSubset inName inTimeout inTextFormat Result Type Text Text Text Number/Batch/Text Text Number Number RowSet
Description Path to file Delimiter between rows Delimiter between columns Maximum rows/row subset Persistent name Timeout in minutes Storage format of text RowSet object
Discussion This method creates a RowSet in exactly the same way as newFromData, but the data comes from the text file located at inPath. For information on working with documents and paths, see Working with Paths on page 92.
540
Chapter 12
Standard Libraries
RowSet
Active4D v5
newFromSelection
newFromSelection(inMainTable; inColumnMap {; inSubset {; inRowCallback {; inName {; inTimeout}}}}) Longint Parameter inMainTable inColumnMap inSubset inRowCallback inName inTimeout Result Type Table pointer Text Number/Batch/Text Text Text Number RowSet Description Pointer to main table Virtual column mapping Maximum rows/row subset Code to execute when loading a row Persistent name Timeout in minutes RowSet object
Discussion This method creates a RowSet from a selection of records in the table pointed to by inMainTable. The columns in the RowSet are determined by inColumnMap, which maps virtual column names to values, which can either be database fields or executable expressions. The column map is formatted as a semicolon-delimited list of column:value pairs. Whitespace before and after the column name and value is ignored. If inSubset is a positive number, it is taken as the maximum number of rows to allow in the RowSet. In this case the start index of the RowSet will be 1 and the end index will be the number of rows in the source data or inSubset, whichever is less. If inSubset is a negative number, this means you would like to allow an unlimited number of rows. In this case the start index of the RowSet will be 1 and the end index will be the number of rows in the source data. If inSubset is a Batch collection reference, the start index of the RowSet will be $inSubset{"start"} and the end index will be $inSubset{"end"}. If inSubset is text, it should be in the form <start>:<end> For example, to use only rows . 10-20 of the source data, you would pass the string 10:20 in inSubset. If inSubset in passed in this manner, the start index of the RowSet will be <start> and the end index will be <end> or the number of rows in the source data, whichever is less. If inName is passed and is non-empty, the RowSet will be persistent and will replace any previous persistent RowSet with that name. If inTimeout is passed and is > 0, a call to timedOut will return true after inTimeout minutes. If inTimeout is not passed or is <= 0, timedOut will always return False, unless setTimeout is subsequently called with a value greater than zero. Note: If you pass inName and create a persistent RowSet, it is effectively the same as calling newFromCachedSelection.
Chapter 12
Standard Libraries
541
Active4D v5
RowSet
Note the use of a literal heredoc string so the column mapping is clearer to the eye. Of course you could do this:
$map := "name:[contacts]name; birthdate: [contacts]birthdate; ...
but it is a lot harder to see the mapping and to add/delete columns later on. If a value references a table which is not the same as the table pointed to by inMainTable, Active4D will turn on auto-loading of related one records. For example, suppose we want to add a company column to the RowSet in Example 1, whose value is [companies]name. The column map would then become: Example 2
$map := """ id: [contacts]id; name: [contacts]name; birthdate: [contacts]birthdate; gender: [contacts]gender; company: [companies]name"""
If there is an automatic relation between [contacts] and [companies], there is nothing more that needs to be done. The RowSet will take care of loading the related [companies] record each time a [contacts] record is loaded. But what if there is no automatic relation between [contacts] and [companies]? Ordinarily you would think of doing something like this in your web page:
542
Chapter 12
Standard Libraries
RowSet
Active4D v5
Example 3
<% $row := $rs->getRow while ($rs->next) // have to load [companies] record query([companies]; [companies]id = [contacts]company_id) %> <tr> <td><%=$row{"name"}%></td> <td><%=$row{"birthdate"}%></td> <td><%=$row{"gender"}%></td> <td><%=$row{"company"}%></td> </tr> <% end while %>
Whats wrong with this picture? You are making a direct reference to a database table within code that is meant to format output. This is a Bad Thing for two reasons:
3 It breaks the insulation from hardcoded data sources that RowSets provide. If you have
to write code like Example 3 you might as well not use RowSets.
3 If you are using Fusebox, the code above would belong to a display fuse, which is never
allowed to reference the database. All database references belong to query fuses. So how can we accomplish this within the context of the RowSet? The answer is by using a row calback. If an expression is passed in inRowCallback, it will be executed just after each record in the main table is loaded, but before the column values are set. Thus the query performed in Example 3 above would become part of the RowSet constructor call, like this: Example 4
$map := """ id: [contacts]id; name: [contacts]name; birthdate: [contacts]birthdate; gender: [contacts]gender; company: [companies]name""" $cb := "query([companies]; [companies]id = [contacts]company_id)" $rs := RowSet.newFromSelection(->[contacts]; $map; -1; $cb)
Lets extend this example by adding a column supervisor from a third table, [employees], which is not directly related to [contacts] at all, but whose current record is derived from some complex set of database operations that is already coded in an Active4D library method called contacts.getSupervisor. In this case we will take advantage of the fact that the row callback can be a block of code with more than one line, since it is executed using the Active4D execute command. So our new version of the RowSet construction looks like this:
Chapter 12
Standard Libraries
543
Active4D v5
RowSet
Example 5
$map := """ id: [contacts]id; name: [contacts]name; birthdate: [contacts]birthdate; gender: [contacts]gender; company: [companies]name supervisor:[employees]name""" $cb := """ query([companies]; [companies]id = [contacts]company_id) contacts.getSupervisor([contacts]id)""" $rs := RowSet.newFromSelection(->[contacts]; $map; -1; $cb)
Note how we took advantage of heredoc strings to write multiple lines of code in the $callback variable. Now let us extend this example one more time to examine the ability to use expressions instead of fields for column values. Suppose the database is changed such that the [contacts]name is split into four fields: [contacts]title, [contacts]first_name, [contacts]middle_initial and [contacts]last_name. You could change the column map to include the four different fields, then concatenate the four fields in your display code, like this: Example 6
$map := """ id: [contacts]id; title: [contacts]title; firstname: [contacts]first_name; mi: [contacts]middle_initial; lastname: [contacts]last_name; birthdate: [contacts]birthdate; gender: [contacts]gender; company: [companies]name supervisor:[employees]name""" // display code <td><%=concat(" "; $row{"title"}; $row{"firstname"}; \\ $row{"mi"}; $row{"lastname"}) %></td>
While you could do this, you shouldnt, because you are effectively tying yourself to the database structure in your display code. What you really want is a virtual database field that concatenates the four fields together. You can accomplish this easily by using an expression as the column value in the column map. To use an expression as the column value, enclose any valid Active4D expression which returns a value in a pair of backticks (``). The expression will be evaluated after each record is loaded and the row callback is executed. This allows us to change the column map and display code in Example 6 to the following:
544
Chapter 12
Standard Libraries
RowSet
Active4D v5
Example 7
$map := """ id: [contacts]id; name: concat(" "; [contacts]title; [contacts]first_name; contacts]middle_initial; [contacts]last_name); birthdate: [contacts]birthdate; gender: [contacts]gender; company: [companies]name supervisor:[employees]name""" // display code <td><%=$row{"name"}%></td>
Note that the display code is the same as in Example 3, which means it did not have to change, even though a huge change was made to the database structure! Together with row callbacks, column expressions give you unparalleled power to isolate the database from the rest of your code. And since any valid Active4D expression can be used, you can call a method as well. Overall selection-based RowSets give you much of the expressive power of SQL. Note: Unlike row callbacks, column expressions may only be one line of code. If you need to execute multiple lines of code, put them in a method and call the method. To Cache or Not to Cache? There are two types of selection-based RowSets: cached and non-cached. This method creates a non-cached RowSet, which means that every time you go to a row a record has to be loaded from the database, the row callback has to be executed, column data has to be copied from the record, and column expressions have to be executed. The method newFromCachedSelection creates a cached RowSet, which means all of the row data is preloaded into memory when the RowSet is created, and all of the above mentioned operations only occur once. There are several factors which might influence the decision whether or not to use cached RowSets:
3 If the number of rows and columns is very large you may have to worry about memory
usage, however the memory is freed as soon as the request is processed.
3 If you will be accessing the RowSet multiple times for example if you need to do a
search within the RowSet before displaying it then a cached RowSet will be faster, since loading data from an array is faster than loading a record and accessing its fields, especially if Active4D is running on Client.
3 If there is no row callback and no column expressions, a cached RowSet will use
SELECTION TO ARRAY to load the data. If Active4D is running on Client, and if the number of columns used in the RowSet is a small subset of the fields in the source table, or the source table contains large text, BLOB or picture fields, then SELECTION TO ARRAY is faster than a row-by-row loading of records because only data from the requested fields is sent to the Client.
Chapter 12
Standard Libraries
545
Active4D v5
RowSet
next
next(self ) Boolean Parameter self Result Type RowSet Boolean Description RowSet reference True if there is a next row
version 3
Discussion This method moves the RowSet cursor to the next row in the RowSet and loads its data. If the cursor was not the last row of the RowSet before this call, True is returned, else False.
persistent
persistent(inName) Collection Parameter inName Result Type Text RowSet
version 4.0
Discussion This method returns a reference to the persistent RowSet named inName. If no such persistent RowSet exists, zero is returned.
previous
previous(self ) Boolean Parameter self Result Type RowSet Boolean
version 3
Discussion This method moves the RowSet cursor to the previous row in the RowSet and loads its data. If the cursor was not the first row of the RowSet before this call, True is returned, else False.
546
Chapter 12
Standard Libraries
RowSet
Active4D v5
rowCount
rowCount(self ) Longint Parameter self Result Type RowSet Longint Description RowSet reference Number of rows in RowSet
version 3
Discussion This method returns the number of rows in the RowSet. To get the number of rows in the data source on which the RowSet is based, use sourceRowCount.
setColumnArray
setColumnArray(self; inColumn; inArray) Parameter self inColumn inArray Type RowSet Text Array Description RowSet reference Virtual column to set Column data
version 3
Discussion If the RowSet self does not already have a column named inColumn, a new column will be added with the given name and data. If a column already exists with the same name, its data is replaced. If the size of inArray is less than rowCount, it is expanded accordingly. If the size of inArray is larger than rowCount, any other columns are expanded accordingly. If maxRows >= 0, the size of the columns is clipped to that. This method is designed to be used in cases where the bulk of your data is noncalculated but one column needs to be calculated.
Chapter 12
Standard Libraries
547
Active4D v5
RowSet
setColumnData
setColumnData(self; inColumn; inData {; inDelimiter}) Parameter self inColumn inData inDelimiter Type RowSet Text Array Text Description RowSet reference Virtual column to set Column data Row delimiter
version 3
Discussion This method functions like setColumnArray, but the column data comes from delimited data instead of an array. If inDelimiter is not passed, it defaults to , .
setRelateOne
setRelateOne(self; inRelateOne) Boolean Parameter self inRelateOne Result Type RowSet Boolean Boolean
Description RowSet reference True to load related one records Old value of flag
Discussion This method sets the auto relate one flag, which determines whether related one records will be loaded when moving the cursor in a RowSet that was created with newFromSelection. The old value of the flag is returned.
548
Chapter 12
Standard Libraries
RowSet
Active4D v5
setTimeout
setTimeout(self; inTimeout) Parameter self inTimeout Type RowSet Number Description RowSet reference Timeout in minutes
version 4.0
Discussion This method sets the timeout of self to inTimeout minutes after selfs creation. In most cases this method is unnecessary, as you can pass the timeout when you create a RowSet.
sort
sort(self; inSortMap) Parameter self inSortMap Type RowSet Text
version 4.0
Discussion This method sorts the data in self according to the sort specification given in inSortMap. The RowSet must have been created with:
Chapter 12
Standard Libraries
549
Active4D v5
RowSet
Example
$map := "lastname:<;firstname:>" $rowset->sort($map) // RowSet will be sorted by lastname descending // and firstname ascending.
sourceRowCount
sourceRowCount(self ) Longint Parameter self Result Type RowSet Longint
version 3
Discussion This method returns the number of rows in the data source on which the RowSet is based. To get the number of rows in the RowSet itself, use rowCount. Note: If the RowSet was created with newFromData/newFromFile and a subset of rows, this method will return the same as getEnd.
timedOut
timedOut(self ) Boolean Parameter self Result Type RowSet Boolean
version 4.0
Discussion If self has a timeout value <= 0, this method returns False. Otherwise this method calculates the difference between the current timestamp and the creation timestamp of self, and if the result is greater than selfs timeout, True is returned, else False.
550
Chapter 12
Standard Libraries
CHAPTER 13 ..............................................................
Debugging
Although Active4D does not have an interactive debugger, there are many tools you can use to find out what is going on inside your code. This requires putting some extra debug code in your scripts, but such is life.
The Basics
There are several basic techniques for peeking inside your code to see what is going on. The technique you use will depend on what the code is doing and whether it is possible to write debugging information to the page.
Using write
The simplest way to find out the internal state of Active4D is to use one of the write commands to write debugging information to your page, like this:
for($i; 1; records in selection([Ingredients])) goto selected record([Ingredients]; true) writebr([Vendors]Name) // debug code // normal code end for
Tracing execution
In some cases you will come across an error in your code which you cannot explain. In such cases, often the line that caused the error is expecting some condition that was not fulfilled, and the actual bug is in code that came earlier. For example, consider the following code:
$c := new collection $c{"foo"} := "bar" include("bar.a4d") // in bar.a4d writebr("%d-%d-%d" % (year of($c{"bar"}); \\ month of($c{"bar"}); \\ day of($c{"bar"}))) // above line fails, $c{"bar"} not set
The error message you receive will be that Active4D was expecting a date in the expression year of($c{"bar"}). Lets pretend there is a lot of code and HTML between the
Chapter 13
Debugging
551
Active4D v5
creation of $c and the write statement in bar.a4d, and you are sure something in there was supposed to set $c{"bar"}. Obviously it isnt happening, so you have to work your way back from the line that caused the error and figure out what went wrong. There are two strategies you can take:
3 Dump debugging information and stopping execution before the error occurs.
Note that in the second case, you must stop execution, otherwise the debugging information you dump will be replaced by the error message when the error occurs. To stop execution, you would do something like this in a Fusebox fuse or layout:
a4d.debug.dump collection($c; ""; true) return
Why return? Because return will halt execution only of the current include file. If you halt execution entirely, the Fusebox core will not have a chance to continue execution to the point where your debug output is actually written to the response buffer. If you are not using Fusebox, you would do something like this:
a4d.debug.dump collection($c; ""; true) exit
In this case you want to use the exit command, which halts all execution.
552
Chapter 13
Debugging
Active4D v5
For details on the a4d.debug methods, see a4d.debug on page 402. For details on the a4d.console methods, see a4d.console on page 398.
3 Information about the host environment 3 Loading of configuration files 3 Loading and unloading of libraries 3 License key file information 3 Internal and runtime errors
Each log entry occupies one logical line and looks something like this:
Oct 20 09:37:57 Active4D: [info] license: matched IP address: 192.168.1.7
Log entries contain the date and time of the entry, followed by Active4D: followed by , the entry type, followed by the message. For non-runtime error messages, the message is prefixed with the module within Active4D where the message originated. For example, the entry above originated in the license module. When a runtime error occurs, the log message contains the error message, followed by the location of the error. Here is a typical syntax error log entry:
Oct 20 19:43:05 Active4D: [error] Syntax error: /Users/aparajita/Active4D-v11/demo.4dbase/web/dsp_basics.a4d, line 22
3 notice: Official announcements 3 warn: Conditions that may cause problems or errors and should be looked into 3 error: Internal or runtime errors that should be attended to, and error messages
logged with the log message command
Chapter 13
Debugging
553
Active4D v5
3 debug: Detailed information about Active4Ds internal operations Changing the Log Level
If the normal logging does not provide enough information to debug a problem, or if you would like to disable logging altogether, you can change the log level. To change the log level, follow these steps: 1 2 3 4 In a text editor, create a new plain text document. In the document, enter the text debug or off . Save the document as log_level in the Active4D log directory. Restart 4D.
If Active4D finds log_level (or for backward compatibility, log_debug_level) in the log directory and it contains debug or off the log level is set accordingly. ,
3 When the log level is debug you will see many log extra entries of type debug This , .
level gives you detailed information about the inner workings of Active4D.
554
Chapter 13
Debugging
Active4D v5
Once the session editor appears, you will see a screen something like this:
The upper part of the session editor contains the fields and controls you use to edit the session. The lower part of the session editor displays the contents of the current session. The elements of the session editor are:
3 Item key: Enter the name of the session item you wish to set or get the value of. 3 Value type: When setting an item, this popup determines what type of value will be
set. You may change the type of an existing session item by using this popup.
3 Array index: If you are setting or getting an element of an array item, specify its index
here.
Chapter 13
Debugging
555
Active4D v5
3 Value: When setting an item, you enter the value here. The text you enter is converted
according to the type set in the Value type popup menu. If you are setting an array, you can enter multiple items. For example, to set a Longint item array with four elements, select Array Longint from the Value type popup menu and enter 1 2 3 4 in this field.
3 Array separator: By default, a space is the array separator used to parse array
elements in the Value field. If you want to use another separator, enter the character in this field. For example, to set a text array with two elements, O give me and a home , you would enter , in the Array separator field and the text O give me,a home in the Value field.
3 Set button: Use this button to set an item with the values you have specified. If no
item with the specified item key exists, a new item will be added to the current session with the given key and value.
3 Get button: Use this button to retrieve the value of the specified item or item array
element.
3 Delete button: Use this button to delete the item specified by Item key. 3 Abandon button: Use this button to abandon the session entirely. After clicking this
button the display may not change, but the session has been abandoned. To update the display, click the Get button after clicking Abandon.
3 Set Timeout button: The current timeout (in minutes) is always displayed in the field
to the left of this button. To change the timeout, enter a new number (fractional minutes are allowed) in the field and click the button.
556
Chapter 13
Debugging
Active4D v5
3 ID: The internal session ID. 3 Timeout: The timeout of the session in minutes. 3 Remaining: The time remaining before the session times out in HH:MM:SS format. 3 Size: The memory usage of the session.
The session list is sorted by time remaning by default. You can select the sort column by clicking on the column header. The current sort column is indicated by being drawn in a darker shade of gray. Below the session list is summary information, which includes the number of sessions and the total memory usage of all sessions. The session list and summary information are updated every five seconds. Viewing Session Data You can view the data in a particular session by double-clicking on it in the list or by selecting it and pressing Return. This displays the session data view, which looks something like this:
Chapter 13
Debugging
557
Active4D v5
The upper part of the session data view displays all of the items in the session. The lower part of the session data view displays a textual representation of the selected item. Arrays are displayed as a CR-delimited list of elements. Clicking on an item in the upper list displays its value below. To return to the session list, click the List button or press Return.
558
Chapter 13
Debugging
Active4D v5
You can turn the console on or off globally by clicking on the On checkbox. In addition, you can have console messages prefixed by the time and/or IP address of the source by checking the Time and IP checkboxes. The console log is automatically cleared when it reaches 5K in size. If you want to clear it before then, click the Clear button. The debugging console works both with 4D standalone and with Client/Server. When run under Client with 4D Server acting as the web server, console messages are queued on Server and retrieved by the Clients on a first come, first serve basis. Each Client that has the console on checks the Server once per second to see if any console messages are queued. If so, all of the queued messages are copied and removed from the queue. Thus only one workstation may view any queued console messages.
The IP Filter section determines which messages are displayed in the console. If the None radio button is selected, all console messages will be displayed. If you select the List radio
Chapter 13
Debugging
559
Active4D v5
button, you may enter a carriage return-delimited list of IP addresses to listen to. To make the filter list active, click the Apply button. For example, the following list would cause the console to listen to only two IP addresses: 192.168.1.7 192.168.1.13 You may also use a * at the end of an IP address to indicate that any address within a subnet is valid. For example, the address: 192.168.1.* would allow the console to listen to any IP address within the range 192.168.1.0 through 192.168.1.255. When you close the Preferences dialog, your filter list is saved to a preferences file on your machine and is read back in the next time you launch the shell.
560
Chapter 13
Debugging
CHAPTER 14 ..............................................................
Error Handling
Active4D goes to considerable lengths to catch errors and display meaningful error messages. If any errors occur during the execution of an Active4D program, execution is immediately aborted and the error handler takes over. The error handler will do one of two things:
3 Display a default error message. 3 Attempt to execute the current error page.
First Active4D shows you the call chain, starting from the least recent at the top to the most recent at the bottom. Included files are all listed separately as part of the chain. After the call chain, the offending line of code is displayed, followed with a message describing what went wrong. The error-causing line is displayed with the following color coding:
3 blue: Tokens already evaluated. 3 red: The offending token or the last token in the offending expression. 3 gray: Tokens not yet evaluated.
Chapter 14
Error Handling
561
Active4D v5
This makes it easy to find the exact cause of the error. Note: The line number for source files is the absolute line number within the file, whereas the line number for a method is the line number of the body of that method, not of the file containing the method. Since empty lines are stripped out of methods, the line number does not include empty lines.
3 Set the error page option in Active4D.ini 3 Call set error page within Active4D
If the designated error page cannot be found, is in a forbidden directory, or an error occurs during the execution of the error page, Active4D falls back to the default error message.
562
Chapter 14
Error Handling
Active4D v5
wish to save and restore the current error page setting, use the get error page command.
All of the above variables are Text except for $a4d_err_line_num and $a4d_err_type, which are Longints. The values used by $a4d_err_type have 4DK# constants defined so you can test against them in your code. The error types are: Type A4D Error Type Unexpected A4D Error Type Syntax A4D Error Type Database A4D Error Type IO A4D Error Type Critical A4D Error Type Runtime Description An error occurred that could not be classified by Active4D A syntax error was encountered in your code A database engine error occurred during the execution of a database command An I/O error occurred during the execution of a document command or a file could not be found A potentially fatal condition has occurred such as running out of memory A runtime error such as a bad array index has occurred
You may wish to use common Active4D code that will do something different in the context of an error page. You can doing this by using the in error command. Within the context of an error page execution this command returns the Boolean value True, otherwise False.
Chapter 14
Error Handling
563
Active4D v5
Assume we have set the error page option in Active4D.ini to act_handleError.a4d Here . is what act_handleError.a4d should look like:
<% fusebox.handleError("home.handleError") %>
Of course you may change home.handleError to whatever fuseaction you wish. The fbx_switch.a4d of our home circuit would have a case like this:
case of :($fusebox{"fuseaction"} = "handleError" include("dsp_handleError.a4d")
The dsp_handleError.a4d display fuse would hopefully display some meaningful message, perhaps log the error that occurred, and then execute the following to clean up:
fusebox.postHandleError
564
Chapter 14
Error Handling
Active4D v5
Setting the log level option sets the default log level for all future Active4D sessions. Calling set log level within Active4D sets the log level dynamically within a single Active4D execution.
Log Levels
There are four error log levels, each with an associated named constant. Each level has an associated bit flag. Named constant A4D Log Off A4D Log Critical Errors A4D Log User Messages A4D Log Execution Errors Value 0 1 2 4 Description No messages are logged Fatal runtime errors like out of memory User message logged through the log message command Execution errors such as syntax errors
You can set exactly which types of errors are logged by adding the bit flags together and using that value. If you are setting the log level within Active4D code, you can used the named constants and also use the bitwise operators | (OR) or ^| (XOR) to set or clear one flag. To turn logging off completely, set the log level to zero. The default log level is 7, which logs all messages. You can retrieve the current log level within Active4D with the get log level command.
Chapter 14
Error Handling
565
Active4D v5
566
Chapter 14
Error Handling
APPENDIX A ..............................................................
Index of Commands
_form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 _query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 _request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300 {} (appending index) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 {-<index>} (from end index) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 % (formatting operator) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 %% (formatting operator) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 A4D Base64 decode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 A4D Base64 encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 A4D Blowfish decrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 A4D Blowfish encrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 A4D Execute <type> request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62 A4D Execute 4D request. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .65 A4D Execute BLOB request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .65 A4D Execute BLOB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69 A4D Execute file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .68 A4D Execute stream request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .66 A4D Execute text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69 A4D FLUSH LIBRARY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 A4D Get IP address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 A4D GET LICENSE INFO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 A4D Get MAC address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 A4D Get MAC address . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 A4D Get root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 A4D GET SESSION DATA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 A4D GET SESSION STATS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390 A4D Get time remaining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 A4D Get version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 A4D Import library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 A4D MD5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 A4D Native to URL path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 A4D RESTART SERVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 A4D Set HTTP body callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 A4D SET ROOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 A4D STRIP 4D TAGS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 A4D URL decode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 A4D URL decode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 A4D URL encode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Appendix A
Index of Commands
567
Active4D v5
A4D URL encode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4D URL to native path. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . abandon response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . abandon session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . add element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . add to timestamp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . add . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addCSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addDateTime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addDumpStyles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addFunction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addJavascript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addJS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addMetaTag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addRowSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . addSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . afterLast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ALL RECORDS, FIRST/LAST/NEXT/PREVIOUS RECORD . . . Append document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . append to array. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . append . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . applyToSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ARRAY <type> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . arrayToList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . articleFor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auth password . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auth type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auth user . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . authenticate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . auto relate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . base64 decode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . base64 encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . beforeFirst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blob to collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blob to session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blobToCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blobToSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blowfish decrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . blowfish encrypt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buffer size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . build query string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromArrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromLists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromOptionArray . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromOptionList . . . . . . . . . . . . . . . . . . . . . . . . . . . . buildOptionsFromRowSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
395 396 289 325 139 371 410 503 413 515 414 516 415 517 517 519 415 418 528 310 356 139 431 442 140 431 442 378 378 378 379 310 165 166 528 152 319 443 443 167 168 273 247 467 468 469 470 471
568
Appendix A
Index of Commands
Active4D v5
buildOptionsFromSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . call 4d method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . call method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . camelCaseText. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . capitalize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . changeDelims . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . checkboxState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . checkSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . choose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . chopText . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear buffer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clear response buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . clearPersistent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collection has . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collection to blob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collectionItemsToQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collectionToBlob. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . collectionToQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . columnCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . compare strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . concat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . contains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . containsNoCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . COPY ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . copy collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . copy upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count collection items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Count in array. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count request cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count request infos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count response cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count response headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count session items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . count uploads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Create document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . cud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current library name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current line number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current method name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
472 214 214 444 333 333 432 473 473 215 444 140 273 156 273 528 162 152 150 474 445 475 529 334 335 432 433 141 154 191 509 163 199 206 141 247 263 266 288 292 324 192 356 446 356 183 183 183
Appendix A
Index of Commands
569
Active4D v5
current path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . current realm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . currentRow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . day of year . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deep clear collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deep copy collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . default directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . define . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . defined. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete collection item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DELETE FOLDER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete response header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . delete session item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Delete string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deleteAt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . deleteSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . directory exists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . directory of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . directory separator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump license info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump license info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump locals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump session stats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dumpDefaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dumpLib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . dumpPersistent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedCollectionItems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedFormVariableList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
357 300 379 529 178 178 156 154 358 217 381 163 358 207 289 293 324 335 433 451 359 359 359 399 403 399 403 400 404 400 404 405 400 405 401 406 405 406 407 401 407 530 490 503 529 475 477 477
570
Appendix A
Index of Commands
Active4D v5
embedFormVariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedQueryParams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . embedVariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . enclose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeBoolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeDate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . encodeString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . end save output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . endArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . endObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . execute in 4d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EXECUTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . extension of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Field name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . file exists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . filename of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fill array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . filterCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . find . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . findColumn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . findNoCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . findRow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first not of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . first . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . for each/end for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . for each/end for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . form variables has . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . format string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . formatUSPhone. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . formVariableListToQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . full requested url . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fuseboxNew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get auto relations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get cache control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get call chain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection array size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection item count. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get content charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
477 478 478 336 426 426 427 427 428 429 276 422 424 219 219 360 172 360 360 142 452 433 530 434 530 337 338 434 531 210 220 196 196 338 452 479 300 504 311 295 184 158 157 159 158 159 157 297
Appendix A
Index of Commands
571
Active4D v5
get content type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get current script timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get error page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get expires date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get field numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get field pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variable choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variable count . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get form variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global array size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Get indexed string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get item value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get license info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get log level. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get output charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get output encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get platform charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Get pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query param choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query param count . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query param . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request infos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get request value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response header. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get response headers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get script timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session array size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
297 306 187 296 295 172 173 197 198 197 199 204 203 204 205 202 270 212 211 211 211 301 381 187 277 278 304 222 244 245 244 246 262 263 265 265 268 274 287 287 288 285 285 291 291 361 305 320
572
Appendix A
Index of Commands
Active4D v5
get session array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session stats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session timeout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get time remaining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get timestamp datetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload content type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload remote filename . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get upload size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get utc delta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . get version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getAt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getColumn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getDefaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getEmptyFields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getEnd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getMailMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getPersistentList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getPictureDescriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getPointerReferent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getRow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPAuthorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPAuthPassword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPAuthUser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getSMTPHost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getStart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getStarts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getTimeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getTitle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getUniqueID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getURLFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . getVariablesIterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . globals has . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GOTO RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GOTO SELECTED RECORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gotoRow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . handleError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . hide session field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . hideField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . hideUniqueField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . html encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
320 321 321 328 328 319 302 373 192 192 193 193 194 179 302 434 531 532 490 479 532 453 532 453 454 533 454 455 455 455 533 491 533 519 480 509 480 223 202 202 311 312 534 509 327 481 481 342
Appendix A
Index of Commands
573
Active4D v5
identical strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . image.a4d (script file). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . in error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . include into . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . insert into array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Insert string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . insertAt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . interpolate string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . is a collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . is an iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . is array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isAfterLast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isBeforeFirst. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isFirst . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isFuseboxRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . isLast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . join array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . join paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last not of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . last . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . left trim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . len. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . library list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . listToArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . load collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . local datetime to utc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . local time to utc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . local variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lock globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . log message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . longint to time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mac to html . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . mac to utf8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . makeFuseboxLinks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . makeLinks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . makeURL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . max of. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . maxRows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . md5 sum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . merge collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . method exists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . min of . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . more items. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MOVE DOCUMENT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
339 234 224 187 225 224 143 339 435 340 161 212 143 534 535 535 510 535 144 361 340 341 435 536 341 436 184 436 153 179 180 382 207 188 225 342 343 491 492 510 232 536 170 155 226 232 210 362
574
Appendix A
Index of Commands
Active4D v5
move . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536 multisort arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 multisort named arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 native to url path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 new collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 new global collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 new local collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 newFromArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496 newFromArrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 newFromCachedSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 newFromData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 newFromFile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540 newFromRowSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496 newFromSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497 newFromSelection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541 next item . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 nextID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456 nil pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Open document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 ORDER BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 ordinalOf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456 param text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 parameter mode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 parseConfig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457 persistent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 Position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 postHandleError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511 prepend. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 previous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498 previous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 qualify. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437 QUERY BY FORMULA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 query params has . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 query params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 QUERY SELECTION BY FORMULA. . . . . . . . . . . . . . . . . . . . . . . . . 175 QUERY SELECTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 QUERY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 QUERY/QUERY SELECTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 random between . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 RECEIVE PACKET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 ReceiveCallback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67 redirect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 regex callback replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
Appendix A
Index of Commands
575
Active4D v5
regex find all in array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex find in array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex match all . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex match . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex quote pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . regex split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . request cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . request info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . request query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . requested url . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . require . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . resize array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . resolve path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RESOLVE POINTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . response buffer size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . response cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . response headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . rest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . reverseArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . right trim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . rowCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . save collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . save output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . save upload to field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . saveFormToSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SELECTION/SELECTION RANGE TO ARRAY . . . . . . . . . . . . . . . SEND PACKET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sendFuseaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sendMail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session has . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session internal id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session to blob. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sessionToBlob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set cache control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set collection array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set content charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set content type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set current script timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SET DOCUMENT POSITION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set error page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set expires date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
251 252 254 253 255 256 259 262 265 303 364 228 146 364 228 273 284 291 437 459 346 547 153 275 194 481 146 365 511 459 323 325 325 326 326 318 318 461 146 295 161 160 298 297 305 365 188 296
576
Appendix A
Index of Commands
Active4D v5
set expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set global array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set log level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set output charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set output encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set platform charset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SET QUERY DESTINATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie expires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response cookie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set response status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set script timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set session array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set session timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setAt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setColumnArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setColumnData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setDefaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setDivId . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setMailMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setRelateOne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setSeparator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setSMTPAuthorization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setSMTPHost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setTimeout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setTitle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . setURLFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . slice string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sourceRowCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . split path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . split string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . startArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . startObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . STRING LIST TO ARRAY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Substring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . time to longint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
296 206 205 382 189 276 277 303 175 274 287 286 288 286 292 298 305 323 327 322 438 547 548 499 505 461 548 505 462 462 549 520 512 229 347 438 549 550 365 348 421 423 271 349 350 175 229 229
Appendix A
Index of Commands
577
Active4D v5
timedOut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp day . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp difference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp hour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp millisecond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp minute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp month . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp second . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp year . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . timestamp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . toJSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . trim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . truncateText . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . type descriptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . undefined . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . unlock globals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . unlockAndLoad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url decode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url decode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url decode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url encode path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url encode query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . url to native path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . utc to local datetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . utc to local time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . utf8 to mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . validateTextFields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . validEmailAddress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . validPrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . valueCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . valueCountNoCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . valueList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . variable name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . warnInvalidField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . week of year . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write blob . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write gif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write jpeg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write jpg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write png . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write raw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write to console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
550 372 374 371 375 376 375 374 376 372 373 374 370 424 350 462 383 383 207 463 351 351 351 352 352 352 366 180 180 353 482 482 464 439 439 439 384 483 181 279 237 238 239 239 282 185 279 425
578
Appendix A
Index of Commands
Active4D v5
Appendix A
Index of Commands
579
Active4D v5
580
Appendix A
Index of Commands
APPENDIX B ..............................................................
French (Swiss) French (Luxembourg) Gaelic German (Standard) German (Swiss) German (Austrian) German (Luxembourg) German (Liechtenstein) Greek Hindi Hungarian Icelandic Indonesian Italian (Standard) Italian (Swiss) Japanese Korean Latvian Lithuanian Macedonian Malaysian Maltese Norwegian Polish Portuguese (Brazilian) Portuguese (Standard) Rhaeto-Romanic Romanian Romanian (Moldavia) Russian Russian (Moldavia) Serbian Slovak Slovenian Sorbian Spanish Spanish (Mexican) Spanish (Guatemala) Spanish (Costa Rica) Spanish (Panama)
fr-ch fr-lu gd de de-ch de-at de-lu de-li el hi hu is in it it-ch ja ko lv lt mk ms mt no pl pt-br pt rm ro ro-mo ru ru-mo sr sk sl sb es es-mx es-gt es-cr es-pa
Appendix B
581
Active4D v5
Spanish Spanish (Venezuela) Spanish (Colombia) Spanish (Peru) Spanish (Argentina) Spanish (Ecuador) Spanish (Chile) Spanish (Uruguay) Spanish (Paraguay) Spanish (Bolivia) Spanish (El Salvador) Spanish (Honduras) Spanish (Nicaragua) Spanish (Puerto Rico) Sutu Swedish Swedish (Finland) Thai Tsonga Tswana Turkish Ukrainian Urdu Vietnamese Xhosa Yiddish Zulu
es-do es-ve es-co es-pe es-ar es-ec es-cl es-uy es-py es-bo es-sv es-hn es-ni es-pr sx sv sv-fi th ts tn tr uk ur vi xh ji zu
582
Appendix B
APPENDIX C ..............................................................
Named Constants
Grouped by Function
Constant HTTP Status OK HTTP Status No Content HTTP Status Found HTTP Status See Other HTTP Status Not Modified HTTP Status Bad Request HTTP Status Unauthorized HTTP Status Forbidden HTTP Status Not Found HTTP Status Request Timeout HTTP Status Request Too Large HTTP Status Server Error A4D Log Off A4D Log Critical Errors A4D Log User Messages A4D Log Execution Errors Position From Start Position From End Position From Current A4D Encoding None A4D Encoding Quotes A4D Encoding Tags A4D Encoding Ampersand A4D Encoding Extended A4D Encoding HTML A4D Encoding All A4D Error Type Unexpected Value 200 204 302 303 304 400 401 403 404 408 413 500 0 1 2 4 1 2 3 0 1 2 4 8 8 65535 1
Appendix C
Named Constants
583
Active4D v5
Constant A4D Error Type Syntax A4D Error Type Database A4D Error Type IO A4D Error Type Critical A4D Error Type Runtime A4D Request Remote Addr A4D Request Host Addr A4D Request Host Port A4D Request Secure A4D Response Version A4D Response Status A4D Response Path A4D Response Mod Date A4D Response Mod Time A4D Charset None A4D Charset Mac A4D Charset Win A4D Charset ISO Latin1 A4D Charset Shift_JIS A4D Charset GB2312 A4D Charset UTF8 A4D Not Executable A4D Parameter Mode Separate A4D Parameter Mode Form A4D Parameter Mode Query A4D License Type Trial A4D License Type Developer A4D License Type Deployment A4D License Type OEM A4D License Type Special A4D Regex Split No Empty A4D Regex Split Capture Delims
Value 2 3 4 5 6 1 2 3 4 1 2 1 2 3 0 1 2 3 4 5 6 -1 0 1 2 0 1 2 3 4 1 2
584
Appendix C
Named Constants
Active4D v5
Alphabetical
Constant A4D Charset GB2312 A4D Charset ISO Latin1 A4D Charset Mac A4D Charset None A4D Charset Shift_JIS A4D Charset UTF8 A4D Charset Win A4D Encoding All A4D Encoding Ampersand A4D Encoding Extended A4D Encoding HTML A4D Encoding None A4D Encoding Quotes A4D Encoding Tags A4D Error Type Critical A4D Error Type Database A4D Error Type IO A4D Error Type Runtime A4D Error Type Syntax A4D Error Type Unexpected A4D License Type Deployment A4D License Type Developer A4D License Type OEM A4D License Type Special A4D License Type Trial A4D Log Critical Errors A4D Log Execution Errors A4D Log Off A4D Log User Messages A4D Not Executable A4D Parameter Mode Form A4D Parameter Mode Query Value 5 3 1 0 4 6 2 65535 4 8 8 0 1 2 5 3 4 6 2 1 2 1 3 4 0 1 4 0 2 -1 1 2
Appendix C
Named Constants
585
Active4D v5
Constant A4D Parameter Mode Separate A4D Regex Split Capture Delims A4D Regex Split No Empty A4D Request Host Addr A4D Request Host Port A4D Request Remote Addr A4D Request Secure A4D Response Mod Date A4D Response Mod Time A4D Response Path A4D Response Status A4D Response Version HTTP Status Bad Request HTTP Status Forbidden HTTP Status Found HTTP Status No Content HTTP Status Not Found HTTP Status Not Modified HTTP Status OK HTTP Status Request Timeout HTTP Status Request Too Large HTTP Status See Other HTTP Status Server Error HTTP Status Unauthorized Position From Current Position From End Position From Start
Value 0 2 1 2 3 1 4 2 3 1 2 1 400 403 302 204 404 304 200 408 413 303 500 401 3 2 1
586
Appendix C
Named Constants