| blib/lib/HTTP/QuickBase.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 69 | 825 | 8.3 |
| branch | 14 | 364 | 3.8 |
| condition | 3 | 28 | 10.7 |
| subroutine | 10 | 73 | 13.7 |
| pod | 32 | 70 | 45.7 |
| total | 128 | 1360 | 9.4 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package HTTP::QuickBase; | ||||||
| 2 | |||||||
| 3 | #Version $Id: QuickBase.pm,v 1.55 2013/08/09 15:29:23 cvonroes Exp $ | ||||||
| 4 | |||||||
| 5 | ( $VERSION ) = '$Revision: 1.55 $ ' =~ /\$Revision:\s+([^\s]+)/; | ||||||
| 6 | |||||||
| 7 | 1 | 1 | 725 | use strict; | |||
| 1 | 1 | ||||||
| 1 | 32 | ||||||
| 8 | 1 | 1 | 2726 | use LWP::UserAgent; | |||
| 1 | 73643 | ||||||
| 1 | 36 | ||||||
| 9 | 1 | 1 | 907 | use MIME::Base64 qw(encode_base64); | |||
| 1 | 797 | ||||||
| 1 | 11635 | ||||||
| 10 | |||||||
| 11 | =pod | ||||||
| 12 | |||||||
| 13 | =head1 NAME | ||||||
| 14 | |||||||
| 15 | HTTP::QuickBase - Create a web shareable database in under a minute | ||||||
| 16 | |||||||
| 17 | =head1 VERSION | ||||||
| 18 | |||||||
| 19 | $Revision: 1.54 $ | ||||||
| 20 | |||||||
| 21 | =head1 SYNOPSIS | ||||||
| 22 | |||||||
| 23 | # see https://www.quickbase.com/up/6mztyxu8/g/rc7/en/ for details of the underlying API. | ||||||
| 24 | |||||||
| 25 | use HTTP::QuickBase; | ||||||
| 26 | $qdb = HTTP::QuickBase->new(); | ||||||
| 27 | |||||||
| 28 | #If you don't want to use HTTPS or your Perl installation doesn't support HTTPS then | ||||||
| 29 | #make sure you have the "Allow non-SSL access (normally OFF)" checkbox checked on your | ||||||
| 30 | #QuickBase database info page. You can get to this page by going to the database "MAIN" | ||||||
| 31 | #page and then clicking on "Administration" under "SHORTCUTS". Then click on "Basic Properties". | ||||||
| 32 | #To use this module in non-SSL mode invoke the QuickBase object like this: | ||||||
| 33 | |||||||
| 34 | #$qdb = HTTP::QuickBase->new('http://www.quickbase.com/db'); | ||||||
| 35 | |||||||
| 36 | $username="fred"; | ||||||
| 37 | $password="flinstone"; | ||||||
| 38 | |||||||
| 39 | $qdb->authenticate($username, $password); | ||||||
| 40 | $database_name= "GuestBook Template"; | ||||||
| 41 | |||||||
| 42 | #I don't recommend using the getIDbyName method because there are many tables with the same name. | ||||||
| 43 | #Instead you can discover the database_id of your table empirically. | ||||||
| 44 | #Read the follwing article to find out how: | ||||||
| 45 | #https://www.quickbase.com/db/6mztyxu8?a=dr&r=w | ||||||
| 46 | |||||||
| 47 | $database_id = "9mztyxu8"; | ||||||
| 48 | $clone_name = "My Guest Book"; | ||||||
| 49 | $database_clone_id = $qdb->cloneDatabase($database_id, $clone_name, "Description of my new database."); | ||||||
| 50 | |||||||
| 51 | |||||||
| 52 | #Let's put something into the new guest book | ||||||
| 53 | $Name = "Fred Flinstone"; | ||||||
| 54 | $dphone = "978-533-2189"; | ||||||
| 55 | $ephone = "781-839-1555"; | ||||||
| 56 | $email = "fred\@bedrock.com"; | ||||||
| 57 | $address1 = "Rubble Court"; | ||||||
| 58 | $address2 = "Pre Historic Route 1"; | ||||||
| 59 | $city = "Bedrock"; | ||||||
| 60 | $state = "Stonia"; | ||||||
| 61 | $zip = "99999-1234"; | ||||||
| 62 | $comments = "Hanna Barbara the king of Saturday morning cartoons."; | ||||||
| 63 | #if you want to attach a file you need to create an array with the first member of the array set to the literal string "file" and the second | ||||||
| 64 | #member of the array set to the full path of the file. | ||||||
| 65 | $attached_file = ["file", "c:\\my documents\\bedrock.txt"]; | ||||||
| 66 | %record_data=("Name" => $Name,"Daytime Phone" => $dphone, "Evening Phone" =>$ephone,"Email Address" => $email, "Street Address 1" => $address1,"Street Address 2" => $address2,"City" => $city,"State"=>$state,"Zip Code"=>$zip, "Comments" => $comments , "Attached File" => $attached_file ); | ||||||
| 67 | |||||||
| 68 | $record_id = $qdb->AddRecord($database_clone_id, %record_data); | ||||||
| 69 | |||||||
| 70 | #Let's get that information back out again | ||||||
| 71 | %new_record=$qdb->GetRecord($database_clone_id, $record_id); | ||||||
| 72 | #Now let's edit that record! | ||||||
| 73 | $new_record{"Daytime Phone"} = "978-275-2189"; | ||||||
| 74 | $qdb->EditRecord($database_clone_id, $record_id, %new_record); | ||||||
| 75 | |||||||
| 76 | #Let's print out all records in the database. | ||||||
| 77 | |||||||
| 78 | @records = $qdb->doQuery($database_clone_id, "{0.CT.''}"); | ||||||
| 79 | foreach $record (@records){ | ||||||
| 80 | foreach $field (keys %$record){ | ||||||
| 81 | print "$field -> $record->{$field}\n"; | ||||||
| 82 | } | ||||||
| 83 | } | ||||||
| 84 | |||||||
| 85 | #Let's save the entire database to a local comma separated values (CSV) file. | ||||||
| 86 | |||||||
| 87 | open( CSV, ">my_qbd_snapshot.csv"); | ||||||
| 88 | print CSV $qdb->getCompleteCSV($database_clone_id); | ||||||
| 89 | close CSV; | ||||||
| 90 | |||||||
| 91 | #Where field number 10 contains Wilma (the query) | ||||||
| 92 | #let's print out fields 10, 11, 12 and 15 (the clist) | ||||||
| 93 | #sorted by field 14 (the slist) | ||||||
| 94 | #in descending order (the options) | ||||||
| 95 | |||||||
| 96 | @records = $qdb->doQuery($database_clone_id, "{10.CT.'Wilma'}", "10.11.12.15", "14", "sortorder-D"); | ||||||
| 97 | foreach $record (@records){ | ||||||
| 98 | foreach $field (keys %$record){ | ||||||
| 99 | print "$field -> $record->{$field}\n"; | ||||||
| 100 | } | ||||||
| 101 | } | ||||||
| 102 | |||||||
| 103 | #You can find out what you need in terms of the query, clist, slist and options by | ||||||
| 104 | #going to the View design page of your QuickBase database and filling in the form. Hit the "Display" button and | ||||||
| 105 | #look at the URL in the browser "Address" window. The View design page is accessible from any database home | ||||||
| 106 | #page by clicking on VIEWS at the top left and then clicking on "New View..." in the lower left. | ||||||
| 107 | |||||||
| 108 | =head1 REQUIRES | ||||||
| 109 | |||||||
| 110 | Perl5.005, LWP::UserAgent, Crypt::SSLeay (optional unless you want to talk to QuickBase via HTTPS) | ||||||
| 111 | |||||||
| 112 | =head1 SEE ALSO | ||||||
| 113 | |||||||
| 114 | https://www.quickbase.com/up/6mztyxu8/g/rc7/en/ for details of the underlying QuickBase HTTP API | ||||||
| 115 | |||||||
| 116 | =head1 EXPORTS | ||||||
| 117 | |||||||
| 118 | Nothing | ||||||
| 119 | |||||||
| 120 | =head1 DESCRIPTION | ||||||
| 121 | |||||||
| 122 | HTTP::QuickBase allows you to manipulate QuickBase databases. | ||||||
| 123 | Methods are provided for cloning databases, adding records, editing records, deleting records and retrieving records. | ||||||
| 124 | All you need is a valid QuickBase account, although with anonymous access you can read from publically accessible QuickBase | ||||||
| 125 | databases. To learn more about QuickBase please visit http://www.quickbase.com/ | ||||||
| 126 | This module supports a single object that retains login state. You call the authenticate method only once. | ||||||
| 127 | |||||||
| 128 | =head1 METHODS | ||||||
| 129 | |||||||
| 130 | =head2 Creation | ||||||
| 131 | |||||||
| 132 | =over 4 | ||||||
| 133 | |||||||
| 134 | =item $qdb = new HTTP::QuickBase($URLprefix) | ||||||
| 135 | |||||||
| 136 | Creates and returns a | ||||||
| 137 | new HTTP::QuickBase object. | ||||||
| 138 | Use the optional $URLprefix to connect to QuickBase via HTTP instead of HTTPS. | ||||||
| 139 | call the constructor with a URLprefix parameter of "http://www.quickbase.com/db/". | ||||||
| 140 | QuickBase databases are by default not accessible via HTTP. To allow HTTP access to a | ||||||
| 141 | QuickBase database go to its main page and click on "Administration" under "SHORTCUTS". | ||||||
| 142 | Then click on "Basic Properties". Next to "Options" you'll see a checkbox labeled | ||||||
| 143 | "Allow non-SSL access (normally unchecked)". You'll need to check this box to allow HTTP | ||||||
| 144 | access to the database. | ||||||
| 145 | |||||||
| 146 | =back | ||||||
| 147 | |||||||
| 148 | =head2 Authentication/Permissions | ||||||
| 149 | |||||||
| 150 | =over 4 | ||||||
| 151 | |||||||
| 152 | =item $qdb->authenticate($username, $password) | ||||||
| 153 | |||||||
| 154 | Sets the username and password used for subsequent method invocations | ||||||
| 155 | |||||||
| 156 | =back | ||||||
| 157 | |||||||
| 158 | =head2 Finding IDs | ||||||
| 159 | |||||||
| 160 | =over 4 | ||||||
| 161 | |||||||
| 162 | =item $qdb->getIDbyName($dbName) | ||||||
| 163 | |||||||
| 164 | Returns the database ID of the database whose full name matches $dbName. | ||||||
| 165 | I don't recommend using the getIDbyName method because there are many tables with the same name. | ||||||
| 166 | Instead you can discover the database_id of your table empirically. | ||||||
| 167 | Read the follwing article to find out how: | ||||||
| 168 | https://www.quickbase.com/db/6mztyxu8?a=dr&r=w | ||||||
| 169 | |||||||
| 170 | =item $qdb->GetRIDs ($QuickBaseID) | ||||||
| 171 | |||||||
| 172 | Returns an array of all record IDs in the database identified by database ID $QuickBaseID. | ||||||
| 173 | |||||||
| 174 | =back | ||||||
| 175 | |||||||
| 176 | =head2 Cloning and Creating from Scratch | ||||||
| 177 | |||||||
| 178 | =over 4 | ||||||
| 179 | |||||||
| 180 | |||||||
| 181 | =item $qdb->cloneDatabase($QuickBaseID, $Name, $Description) | ||||||
| 182 | |||||||
| 183 | Clones the database identified by $QuickBaseID and gives the clone the name $Name and description $Description | ||||||
| 184 | |||||||
| 185 | Returns the dbid of the new database. | ||||||
| 186 | |||||||
| 187 | =back | ||||||
| 188 | |||||||
| 189 | =over 4 | ||||||
| 190 | |||||||
| 191 | =item $qdb->createDatabase($Name, $Description) | ||||||
| 192 | |||||||
| 193 | Creates a database with the name $Name and description $Description | ||||||
| 194 | |||||||
| 195 | Returns the dbid of the new database. | ||||||
| 196 | |||||||
| 197 | =back | ||||||
| 198 | |||||||
| 199 | =over 4 | ||||||
| 200 | |||||||
| 201 | =item $qdb->addField($QuickBaseID, $label, $type, $mode) | ||||||
| 202 | |||||||
| 203 | Creates a field with the label $label of label, a type of $type and if the field is to be a formula field then set $mode to 'virtual' otherwise set it to the empty string. | ||||||
| 204 | |||||||
| 205 | Returns the fid of the new field. | ||||||
| 206 | |||||||
| 207 | =back | ||||||
| 208 | |||||||
| 209 | =over 4 | ||||||
| 210 | |||||||
| 211 | =item $qdb->deleteField($QuickBaseID, $fid) | ||||||
| 212 | |||||||
| 213 | Deletes the field with the field identifier of $fid. | ||||||
| 214 | |||||||
| 215 | Returns nothing. | ||||||
| 216 | |||||||
| 217 | =back | ||||||
| 218 | |||||||
| 219 | =over 4 | ||||||
| 220 | |||||||
| 221 | =item $qdb->setFieldProperties($QuickBaseID, $fid, %properties) | ||||||
| 222 | |||||||
| 223 | Modifies the field with the field identifier of $fid using the name-value pairs in %properties. Please see the QuickBase HTTP API document for more details. | ||||||
| 224 | |||||||
| 225 | Returns nothing. | ||||||
| 226 | |||||||
| 227 | =back | ||||||
| 228 | |||||||
| 229 | |||||||
| 230 | =head2 Adding Information | ||||||
| 231 | |||||||
| 232 | =over 4 | ||||||
| 233 | |||||||
| 234 | |||||||
| 235 | =item $qdb->AddRecord($QuickBaseID, %recorddata) | ||||||
| 236 | |||||||
| 237 | Returns the record id of the new record. The keys of the associative array %recorddata are scanned for matches with the | ||||||
| 238 | field names of the database. If the key begins with the number one through nine and contains only numbers | ||||||
| 239 | then the field identifiers are scanned for a match instead. | ||||||
| 240 | If a particular key matches then the corresponding field in the new record is set to the value associated with the key. | ||||||
| 241 | If you want to attach a file you need to create an array with the first member of the array set to the string literal 'file' and the second | ||||||
| 242 | member of the array set to the full path of the file. Then the value of the key corresponding to the file attachment field | ||||||
| 243 | should be set to a reference which points to this two member array. | ||||||
| 244 | |||||||
| 245 | =back | ||||||
| 246 | |||||||
| 247 | =head2 Deleting Information | ||||||
| 248 | |||||||
| 249 | =over 4 | ||||||
| 250 | |||||||
| 251 | =item $qdb->DeleteRecord($QuickBaseID, $rid) | ||||||
| 252 | |||||||
| 253 | Deletes the record identified by the record identifier $rid. | ||||||
| 254 | |||||||
| 255 | =back | ||||||
| 256 | |||||||
| 257 | =over 4 | ||||||
| 258 | |||||||
| 259 | =item $qdb->PurgeRecords($QuickBaseID, $query) | ||||||
| 260 | |||||||
| 261 | Deletes the records identified by the query, qname or qid in $query. Use the qid of '1' to delete all the records in a database. | ||||||
| 262 | |||||||
| 263 | Please refer to https://www.quickbase.com/db/6mztyxu8?a=dr&r=2 for more details on the query parameter. | ||||||
| 264 | |||||||
| 265 | =back | ||||||
| 266 | |||||||
| 267 | |||||||
| 268 | |||||||
| 269 | =head2 Editing Information | ||||||
| 270 | |||||||
| 271 | =over 4 | ||||||
| 272 | |||||||
| 273 | =item $qdb->EditRecord($QuickBaseID, $rid, %recorddata) | ||||||
| 274 | |||||||
| 275 | Modifies the record defined by record id $rid in the database defined by database ID $QuickBaseID. | ||||||
| 276 | |||||||
| 277 | Any field in the database that can be modified and that has its field label or field identifer as a key in the associative array | ||||||
| 278 | %recorddata will be modified to the value associated with the key. The keys of the associative array %recorddata are scanned for matches with the | ||||||
| 279 | field names of the database. If the key begins with the number one through nine and contains only numbers | ||||||
| 280 | then the field identifiers are scanned for a match instead. | ||||||
| 281 | If a particular key matches then the corresponding field in the record is set to the value associated with the key. | ||||||
| 282 | If you want to modify a file attachment field, you need to create an array with the first member of the array set to the string literal 'file' and the second | ||||||
| 283 | member of the array set to the full path of the file. Then the value of the key corresponding to the file attachment field | ||||||
| 284 | should be set to a reference which points to this two member array. | ||||||
| 285 | |||||||
| 286 | |||||||
| 287 | Use $qdb->EditRecordWithUpdateID($QuickBaseID, $rid, $update_id, %recorddata) to take advantage of conflict detection. | ||||||
| 288 | If $update_id is supplied then the edit will only succeed if the record's current update_id matches. | ||||||
| 289 | |||||||
| 290 | Returns the XML response from QuickBase after modifying every valid field refered to in %recorddata. | ||||||
| 291 | |||||||
| 292 | Not all fields can be modified. Built-in and formula (virtual) fields cannot be modified. If you attempt to | ||||||
| 293 | modify them with EditRecord you will get an error and no part of the record will have been modified. | ||||||
| 294 | |||||||
| 295 | =back | ||||||
| 296 | |||||||
| 297 | =head2 Retrieving Information | ||||||
| 298 | |||||||
| 299 | =over 4 | ||||||
| 300 | |||||||
| 301 | =item $qdb->GetRecord($QuickBaseID, $rid) | ||||||
| 302 | |||||||
| 303 | From the database identified by $QuickBaseID, returns an associative array of field names and values of the record identified by $rid. | ||||||
| 304 | |||||||
| 305 | =back | ||||||
| 306 | |||||||
| 307 | =over 4 | ||||||
| 308 | |||||||
| 309 | =item $qdb->doQuery($QuickBaseID, $query, $clist, $slist, $options) | ||||||
| 310 | |||||||
| 311 | From the database identified by $QuickBaseID, returns an array of | ||||||
| 312 | associative arrays of field names and values of the records selected by | ||||||
| 313 | $query, which can either be an actual query in QuickBase's query | ||||||
| 314 | language, or a view name or number (qid or qname). | ||||||
| 315 | |||||||
| 316 | The columns (fields) returned are determined by $clist, a period delimited list of field identifiers. | ||||||
| 317 | |||||||
| 318 | The sorting of the records is determined by $slist, a period delimited list of field identifiers. | ||||||
| 319 | |||||||
| 320 | Ascending or descending order of the sorts defined by $slist is controlled by $options. | ||||||
| 321 | |||||||
| 322 | Please refer to https://www.quickbase.com/db/6mztyxu8?a=dr&r=2 for more details on the parameters for API_DoQuery. | ||||||
| 323 | |||||||
| 324 | =back | ||||||
| 325 | |||||||
| 326 | =over 4 | ||||||
| 327 | |||||||
| 328 | =item $qdb->getCompleteCSV($QuickBaseID) | ||||||
| 329 | |||||||
| 330 | From the database identified by $QuickBaseID, returns a scalar containing the comma separated values of all fields including built in fields. | ||||||
| 331 | |||||||
| 332 | The first row of the comma separated values (CSV) contains the field labels. | ||||||
| 333 | |||||||
| 334 | =back | ||||||
| 335 | |||||||
| 336 | =over 4 | ||||||
| 337 | |||||||
| 338 | =item $qdb->GetFile($QuickBaseDBid, $filename, $rid, $fid) | ||||||
| 339 | |||||||
| 340 | From the database identified by $QuickBaseID, returns an array where the first element is the contents of the file $filename uploaded to | ||||||
| 341 | the record identified by record ID $rid in the field identified by field indentifier $fid. | ||||||
| 342 | |||||||
| 343 | The second element of the returned array is return value from the headers method of the corresponding LWP::UserAgent object. | ||||||
| 344 | |||||||
| 345 | =back | ||||||
| 346 | |||||||
| 347 | |||||||
| 348 | |||||||
| 349 | |||||||
| 350 | =head2 Errors | ||||||
| 351 | |||||||
| 352 | =over 4 | ||||||
| 353 | |||||||
| 354 | =item $qdb->error() | ||||||
| 355 | |||||||
| 356 | Retrieve the error code returned from QuickBase. | ||||||
| 357 | Please refer to the | ||||||
| 358 | |||||||
| 359 | Appendix A for error code details. | ||||||
| 360 | |||||||
| 361 | =item $qdb->errortext() | ||||||
| 362 | |||||||
| 363 | Retrieve the error text returned from QuickBase. | ||||||
| 364 | Please refer to | ||||||
| 365 | |||||||
| 366 | Appendix A for all possible error messages. | ||||||
| 367 | |||||||
| 368 | |||||||
| 369 | =back | ||||||
| 370 | |||||||
| 371 | |||||||
| 372 | =head2 New API calls added in 2008 | ||||||
| 373 | |||||||
| 374 | |||||||
| 375 | |||||||
| 376 | |||||||
| 377 | =over 4 | ||||||
| 378 | |||||||
| 379 | =item CreateTable($QuickBaseDBid, $pnoun) | ||||||
| 380 | |||||||
| 381 | Add a table to an existing application. | ||||||
| 382 | |||||||
| 383 | Returns the dbid of the new table. | ||||||
| 384 | |||||||
| 385 | =back | ||||||
| 386 | |||||||
| 387 | |||||||
| 388 | |||||||
| 389 | =over 4 | ||||||
| 390 | |||||||
| 391 | =item AddUserToRole($QuickBaseDBid, $userid, $roleid) | ||||||
| 392 | |||||||
| 393 | Add a user to a role in an application. | ||||||
| 394 | |||||||
| 395 | =back | ||||||
| 396 | |||||||
| 397 | |||||||
| 398 | |||||||
| 399 | =over 4 | ||||||
| 400 | |||||||
| 401 | =item ChangeUserRole($QuickBaseDBid, $userid, $roleid, $newroleid) | ||||||
| 402 | |||||||
| 403 | Change the role of a user in an application. | ||||||
| 404 | |||||||
| 405 | =back | ||||||
| 406 | |||||||
| 407 | |||||||
| 408 | |||||||
| 409 | =over 4 | ||||||
| 410 | |||||||
| 411 | =item GetDBvar($QuickBaseDBid, $varname) | ||||||
| 412 | |||||||
| 413 | Retrieve the value of an application variable. | ||||||
| 414 | |||||||
| 415 | =back | ||||||
| 416 | |||||||
| 417 | =over 4 | ||||||
| 418 | |||||||
| 419 | =item GetRoleInfo($QuickBaseDBid) | ||||||
| 420 | |||||||
| 421 | Retrieve the list of Roles defined for an application. | ||||||
| 422 | |||||||
| 423 | =back | ||||||
| 424 | |||||||
| 425 | =over 4 | ||||||
| 426 | |||||||
| 427 | =item GetUserInfo($email) | ||||||
| 428 | |||||||
| 429 | Retrieve a hash containing the login, name, and id of a user, given the user's email address. | ||||||
| 430 | |||||||
| 431 | =back | ||||||
| 432 | |||||||
| 433 | |||||||
| 434 | =over 4 | ||||||
| 435 | |||||||
| 436 | =item GetUserRole($QuickBaseDBid,$userid) | ||||||
| 437 | |||||||
| 438 | Retrieve the Role information for a user | ||||||
| 439 | |||||||
| 440 | =back | ||||||
| 441 | |||||||
| 442 | =over 4 | ||||||
| 443 | |||||||
| 444 | =item ProvisionUser($QuickBaseDBid,$roleid, $email, $fname, $lname) | ||||||
| 445 | |||||||
| 446 | Add the user information to QuickBase in preparation for inviting the user for the first time to view a QuickBase application. | ||||||
| 447 | |||||||
| 448 | =back | ||||||
| 449 | |||||||
| 450 | |||||||
| 451 | =over 4 | ||||||
| 452 | |||||||
| 453 | =item GetOneTimeTicket | ||||||
| 454 | |||||||
| 455 | Retrieve a ticket valid for the next 5 minutes only. Designed for uploading files. | ||||||
| 456 | |||||||
| 457 | =back | ||||||
| 458 | |||||||
| 459 | =over 4 | ||||||
| 460 | |||||||
| 461 | =item RemoveUserFromRole($QuickBaseDBid, $userid, $roleid) | ||||||
| 462 | |||||||
| 463 | Remove a user from a role in an application. | ||||||
| 464 | |||||||
| 465 | =back | ||||||
| 466 | |||||||
| 467 | |||||||
| 468 | =over 4 | ||||||
| 469 | |||||||
| 470 | =item RenameApp($QuickBaseDBid,$newappname) | ||||||
| 471 | |||||||
| 472 | Change the name of an application. | ||||||
| 473 | |||||||
| 474 | =back | ||||||
| 475 | |||||||
| 476 | |||||||
| 477 | =over 4 | ||||||
| 478 | |||||||
| 479 | =item SetDBvar($QuickBaseDBid, $varname, $value) | ||||||
| 480 | |||||||
| 481 | Set the value of an application variable. | ||||||
| 482 | |||||||
| 483 | =back | ||||||
| 484 | |||||||
| 485 | |||||||
| 486 | =over 4 | ||||||
| 487 | |||||||
| 488 | =item SendInvitation($QuickBaseDBid, $userid) | ||||||
| 489 | |||||||
| 490 | Send an email from QuickBase inviting a user to an application. | ||||||
| 491 | |||||||
| 492 | =back | ||||||
| 493 | |||||||
| 494 | |||||||
| 495 | =over 4 | ||||||
| 496 | |||||||
| 497 | =item UserRoles($QuickBaseDBid) | ||||||
| 498 | |||||||
| 499 | Returns an Xml Document of information about the roles defined for an application. | ||||||
| 500 | |||||||
| 501 | =back | ||||||
| 502 | |||||||
| 503 | |||||||
| 504 | |||||||
| 505 | =head1 CLASS VARIABLES | ||||||
| 506 | |||||||
| 507 | None | ||||||
| 508 | |||||||
| 509 | =head1 DIAGNOSTICS | ||||||
| 510 | |||||||
| 511 | All errors are reported by the methods error and errortext. For a | ||||||
| 512 | complete list of errors, please visit | ||||||
| 513 | https://www.quickbase.com/up/6mztyxu8/g/rc7/en/ and scroll | ||||||
| 514 | down to Appendix A. | ||||||
| 515 | |||||||
| 516 | =head1 AUTHOR | ||||||
| 517 | |||||||
| 518 | Claude von Roesgen, claude_von_roesgen@intuit.com | ||||||
| 519 | |||||||
| 520 | =head1 COPYRIGHT | ||||||
| 521 | |||||||
| 522 | Copyright (c) 1999-2008 Intuit, Inc. All rights reserved. | ||||||
| 523 | This program is free software; you can redistribute it and/or | ||||||
| 524 | modify it under the same terms as Perl itself. | ||||||
| 525 | |||||||
| 526 | |||||||
| 527 | =cut | ||||||
| 528 | |||||||
| 529 | my %XMLescapes; | ||||||
| 530 | |||||||
| 531 | sub new | ||||||
| 532 | { | ||||||
| 533 | 1 | 1 | 1 | 14 | my $class = shift; | ||
| 534 | 1 | 2 | my $prefix = shift; | ||||
| 535 | 1 | 2 | my $self; | ||||
| 536 | |||||||
| 537 | 1 | 4 | for (0..255) { | ||||
| 538 | 256 | 938 | $XMLescapes{chr($_)} = sprintf("%03d;", $_); | ||||
| 539 | } | ||||||
| 540 | |||||||
| 541 | 1 | 50 | 21 | $self = bless { | |||
| 542 | 'URLprefix' => $prefix || "https://www.quickbase.com/db" , | ||||||
| 543 | 'ticket' => undef, | ||||||
| 544 | 'apptoken' => "", | ||||||
| 545 | 'error' => undef, | ||||||
| 546 | 'errortext' => undef, | ||||||
| 547 | 'username' => undef, | ||||||
| 548 | 'password' => undef, | ||||||
| 549 | 'credentials' => undef, | ||||||
| 550 | 'proxy' => undef, | ||||||
| 551 | 'realmhost' => undef | ||||||
| 552 | }, $class; | ||||||
| 553 | |||||||
| 554 | } | ||||||
| 555 | |||||||
| 556 | sub authenticate ($$) | ||||||
| 557 | { | ||||||
| 558 | 1 | 1 | 1 | 13 | my($self, $username, $password) = @_; | ||
| 559 | 1 | 7 | $self->{'username'} = $username; | ||||
| 560 | 1 | 4 | $self->{'password'} = $password; | ||||
| 561 | 1 | 6 | $username = $self->xml_escape($username); | ||||
| 562 | 1 | 11 | $password = $self->xml_escape($password); | ||||
| 563 | 1 | 5 | $self->{'credentials'} = " |
||||
| 564 | 1 | 3 | $self->{'ticket'}=""; | ||||
| 565 | 1 | 2 | return ""; | ||||
| 566 | } | ||||||
| 567 | |||||||
| 568 | sub setAppToken($) | ||||||
| 569 | { | ||||||
| 570 | 0 | 0 | 0 | 0 | my($self,$apptoken) = @_; | ||
| 571 | 0 | 0 | $self->{'apptoken'} = $apptoken; | ||||
| 572 | } | ||||||
| 573 | |||||||
| 574 | sub getTicket() | ||||||
| 575 | { | ||||||
| 576 | 0 | 0 | 0 | 0 | my($self) = @_; | ||
| 577 | #First we have to get the authorization ticket | ||||||
| 578 | #We do this by posting the QuickBase username and password to QuickBase | ||||||
| 579 | #This is where we post the QuickBase username and password | ||||||
| 580 | 0 | 0 | my $res = $self->PostAPIURL ("main", "API_Authenticate", | ||||
| 581 | " |
||||||
| 582 | $self->{'credentials'}. | ||||||
| 583 | ""); | ||||||
| 584 | 0 | 0 | 0 | if ($res->content =~ / |
|||
| 585 | { | ||||||
| 586 | 0 | 0 | $self->{'error'} = $1; | ||||
| 587 | 0 | 0 | $self->{'errortext'} = $2; | ||||
| 588 | } | ||||||
| 589 | 0 | 0 | 0 | if ($res->content =~ / |
|||
| 590 | { | ||||||
| 591 | 0 | 0 | $self->{'errortext'} = $1; | ||||
| 592 | } | ||||||
| 593 | 0 | 0 | 0 | if ($self->{'error'} eq '0') | |||
| 594 | { | ||||||
| 595 | 0 | 0 | $res->content =~ / |
||||
| 596 | 0 | 0 | $self->{'ticket'} = $1; | ||||
| 597 | 0 | 0 | $self->{'credentials'} = " |
||||
| 598 | } | ||||||
| 599 | else | ||||||
| 600 | { | ||||||
| 601 | 0 | 0 | return ""; | ||||
| 602 | } | ||||||
| 603 | 0 | 0 | return $self->{'ticket'}; | ||||
| 604 | } | ||||||
| 605 | |||||||
| 606 | sub URLprefix() | ||||||
| 607 | { | ||||||
| 608 | 1 | 1 | 0 | 3 | my($self) = shift; | ||
| 609 | 1 | 50 | 5 | if (@_) | |||
| 610 | { | ||||||
| 611 | 0 | 0 | $self->{'URLprefix'}=shift; | ||||
| 612 | 0 | 0 | $self->{'URLprefix'} =~ s/cgi\/sb.exe/db/; | ||||
| 613 | 0 | 0 | return $self->{'URLprefix'}; | ||||
| 614 | } | ||||||
| 615 | else | ||||||
| 616 | { | ||||||
| 617 | 1 | 10 | return $self->{'URLprefix'}; | ||||
| 618 | } | ||||||
| 619 | } | ||||||
| 620 | |||||||
| 621 | sub setProxy($) | ||||||
| 622 | { | ||||||
| 623 | 0 | 0 | 0 | 0 | my($self, $proxyserver) = @_; | ||
| 624 | 0 | 0 | $self->{'proxy'} = $proxyserver; | ||||
| 625 | 0 | 0 | return $self->{'proxy'}; | ||||
| 626 | } | ||||||
| 627 | |||||||
| 628 | sub setRealmHost($) | ||||||
| 629 | { | ||||||
| 630 | 0 | 0 | 0 | 0 | my($self, $realmhost) = @_; | ||
| 631 | 0 | 0 | $self->{'realmhost'} = $realmhost; | ||||
| 632 | 0 | 0 | return $self->{'realmhost'}; | ||||
| 633 | } | ||||||
| 634 | |||||||
| 635 | sub errortext() | ||||||
| 636 | { | ||||||
| 637 | 1 | 1 | 1 | 37 | my($self) = shift; | ||
| 638 | 1 | 0 | return $self->{'errortext'}; | ||||
| 639 | } | ||||||
| 640 | |||||||
| 641 | sub error() | ||||||
| 642 | { | ||||||
| 643 | 0 | 0 | 1 | 0 | my($self) = shift; | ||
| 644 | 0 | 0 | return $self->{'error'}; | ||||
| 645 | } | ||||||
| 646 | |||||||
| 647 | sub AddRecord($%) | ||||||
| 648 | { | ||||||
| 649 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid, %recorddata) = @_; | ||
| 650 | 0 | 0 | my $name; | ||||
| 651 | my $content; | ||||||
| 652 | 0 | 0 | my $filecontents; | ||||
| 653 | 0 | 0 | my $filebuffer; | ||||
| 654 | 0 | 0 | my $tag; | ||||
| 655 | |||||||
| 656 | 0 | 0 | $content = " |
||||
| 657 | 0 | 0 | foreach $name (keys(%recorddata)) | ||||
| 658 | { | ||||||
| 659 | 0 | 0 | $tag=$name; | ||||
| 660 | 0 | 0 | $tag =~tr/A-Z/a-z/; | ||||
| 661 | 0 | 0 | $tag=~s/[^a-z0-9]/_/g; | ||||
| 662 | 0 | 0 | $content .= $self->createFieldXML($tag, $recorddata{$name}); | ||||
| 663 | } | ||||||
| 664 | |||||||
| 665 | 0 | 0 | $content .= ""; | ||||
| 666 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_AddRecord", $content); | ||||
| 667 | 0 | 0 | my $xml = $res->content; | ||||
| 668 | |||||||
| 669 | 0 | 0 | 0 | if ($xml =~ / |
|||
| 670 | { | ||||||
| 671 | 0 | 0 | return $1; | ||||
| 672 | } | ||||||
| 673 | 0 | 0 | return ""; | ||||
| 674 | } | ||||||
| 675 | |||||||
| 676 | sub AddReplaceDBPage($$$$$) | ||||||
| 677 | { | ||||||
| 678 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid, $pageid, $pagename, $pagetype, $pagebody) = @_; | ||
| 679 | |||||||
| 680 | 0 | 0 | my $content = " |
||||
| 681 | 0 | 0 | 0 | $content .= " |
|||
| 682 | 0 | 0 | 0 | $content .= " |
|||
| 683 | 0 | 0 | $content .= " |
||||
| 684 | |||||||
| 685 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_AddReplaceDBPage", $content)->content; | ||||
| 686 | |||||||
| 687 | 0 | 0 | 0 | if($res =~ / |
|||
| 0 | |||||||
| 688 | 0 | 0 | return $1; | ||||
| 689 | } | ||||||
| 690 | elsif($res =~ / |
||||||
| 691 | 0 | 0 | return $1; | ||||
| 692 | } | ||||||
| 693 | else | ||||||
| 694 | { | ||||||
| 695 | 0 | 0 | return ""; | ||||
| 696 | } | ||||||
| 697 | } | ||||||
| 698 | |||||||
| 699 | sub AddUserToRole($$$) | ||||||
| 700 | { | ||||||
| 701 | 0 | 0 | 1 | 0 | my($self,$QuickBaseDBid, $userid, $roleid) = @_; | ||
| 702 | 0 | 0 | my $content = " |
||||
| 703 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_AddUserToRole", $content); | ||||
| 704 | 0 | 0 | return ""; | ||||
| 705 | } | ||||||
| 706 | |||||||
| 707 | sub ChangeUserRole($$$$) | ||||||
| 708 | { | ||||||
| 709 | 0 | 0 | 1 | 0 | my($self,$QuickBaseDBid, $userid, $roleid, $newroleid) = @_; | ||
| 710 | 0 | 0 | my $content = " |
||||
| 711 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_AddUserToRole", $content); | ||||
| 712 | 0 | 0 | return ""; | ||||
| 713 | } | ||||||
| 714 | |||||||
| 715 | sub ChangeRecordOwner($$$) | ||||||
| 716 | { | ||||||
| 717 | 0 | 0 | 0 | 0 | my($self, $QuickBaseDBid, $rid, $newowner); | ||
| 718 | |||||||
| 719 | 0 | 0 | my $content = " |
||||
| 720 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_ChangeRecordOwner", $content); | ||||
| 721 | 0 | 0 | return""; | ||||
| 722 | } | ||||||
| 723 | |||||||
| 724 | sub CreateTable($$) | ||||||
| 725 | { | ||||||
| 726 | 0 | 0 | 1 | 0 | my($self,$QuickBaseDBid, $pnoun) = @_; | ||
| 727 | 0 | 0 | my $content = " |
||||
| 728 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_CreateTable", $content)->content; | ||||
| 729 | 0 | 0 | 0 | if($res =~ / |
|||
| 0 | |||||||
| 730 | 0 | 0 | return $1; | ||||
| 731 | } | ||||||
| 732 | elsif($res =~ / |
||||||
| 733 | 0 | 0 | return $1; | ||||
| 734 | } | ||||||
| 735 | else | ||||||
| 736 | { | ||||||
| 737 | 0 | 0 | return ""; | ||||
| 738 | } | ||||||
| 739 | } | ||||||
| 740 | |||||||
| 741 | sub DeleteDatabase($) | ||||||
| 742 | { | ||||||
| 743 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid) = @_; | ||
| 744 | 0 | 0 | $self->PostAPIURL($QuickBaseDBid, "API_DeleteDatabase", ""); | ||||
| 745 | 0 | 0 | return ""; | ||||
| 746 | } | ||||||
| 747 | |||||||
| 748 | sub DeleteRecord($$) | ||||||
| 749 | { | ||||||
| 750 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid, $rid) = @_; | ||
| 751 | |||||||
| 752 | 0 | 0 | my $content = " |
||||
| 753 | " |
||||||
| 754 | ""; | ||||||
| 755 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_DeleteRecord", $content)->content; | ||||
| 756 | } | ||||||
| 757 | |||||||
| 758 | sub FieldAddChoices($$@) | ||||||
| 759 | { | ||||||
| 760 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid, $fid, @choices) = @_; | ||
| 761 | |||||||
| 762 | 0 | 0 | my $content = " |
||||
| 763 | 0 | 0 | my $choice; | ||||
| 764 | 0 | 0 | foreach $choice (@choices) | ||||
| 765 | { | ||||||
| 766 | 0 | 0 | $content .= " |
||||
| 767 | } | ||||||
| 768 | 0 | 0 | $content .= ""; | ||||
| 769 | |||||||
| 770 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_FieldAddChoices", $content)->content; | ||||
| 771 | |||||||
| 772 | 0 | 0 | 0 | if($res =~ / |
|||
| 773 | 0 | 0 | return $1; | ||||
| 774 | } | ||||||
| 775 | else | ||||||
| 776 | { | ||||||
| 777 | 0 | 0 | return ""; | ||||
| 778 | } | ||||||
| 779 | } | ||||||
| 780 | |||||||
| 781 | sub FieldRemoveChoices($$@) | ||||||
| 782 | { | ||||||
| 783 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid, $fid, @choices) = @_; | ||
| 784 | |||||||
| 785 | 0 | 0 | my $content = " |
||||
| 786 | 0 | 0 | my $choice; | ||||
| 787 | 0 | 0 | foreach $choice (@choices) | ||||
| 788 | { | ||||||
| 789 | 0 | 0 | $content .= " |
||||
| 790 | } | ||||||
| 791 | 0 | 0 | $content .= ""; | ||||
| 792 | |||||||
| 793 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_FieldRemoveChoices", $content)->content; | ||||
| 794 | |||||||
| 795 | 0 | 0 | 0 | if($res =~ / |
|||
| 796 | 0 | 0 | return $1; | ||||
| 797 | } | ||||||
| 798 | else | ||||||
| 799 | { | ||||||
| 800 | 0 | 0 | return ""; | ||||
| 801 | } | ||||||
| 802 | } | ||||||
| 803 | |||||||
| 804 | sub GenAddRecordForm($%) | ||||||
| 805 | { | ||||||
| 806 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid,%fields) = @_; | ||
| 807 | 0 | 0 | my $content = " |
||||
| 808 | 0 | 0 | my $field; | ||||
| 809 | 0 | 0 | foreach $field (keys %fields) | ||||
| 810 | { | ||||||
| 811 | 0 | 0 | $content .= " |
||||
| 812 | } | ||||||
| 813 | 0 | 0 | $content .= ""; | ||||
| 814 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GenAddRecordForm", $content)->content; | ||||
| 815 | } | ||||||
| 816 | |||||||
| 817 | sub GenResultsTable($$$$$$$) | ||||||
| 818 | { | ||||||
| 819 | 0 | 0 | 0 | 0 | my($self, $QuickBaseDBid, $query, $clist, $slist, $jht, $jsa, $options) = @_; | ||
| 820 | 0 | 0 | my $content = " |
||||
| 821 | 0 | 0 | 0 | $content .= " |
|||
| 822 | 0 | 0 | 0 | $content .= " |
|||
| 823 | 0 | 0 | 0 | $content .= " |
|||
| 824 | 0 | 0 | 0 | $content .= " |
|||
| 825 | 0 | 0 | 0 | $content .= " |
|||
| 826 | 0 | 0 | 0 | $content .= " |
|||
| 827 | 0 | 0 | $content .= ""; | ||||
| 828 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GenAddRecordForm", $content)->content; | ||||
| 829 | } | ||||||
| 830 | |||||||
| 831 | sub GetDBInfo($) | ||||||
| 832 | { | ||||||
| 833 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid) = @_; | ||
| 834 | |||||||
| 835 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_GetDBInfo", "")->content; | ||||
| 836 | |||||||
| 837 | 0 | 0 | my %dbInfo; | ||||
| 838 | 0 | 0 | 0 | if($res =~ / |
|||
| 839 | 0 | 0 | $dbInfo{"dbname"} = $1; | ||||
| 840 | } | ||||||
| 841 | 0 | 0 | 0 | if($res =~ / |
|||
| 842 | 0 | 0 | $dbInfo{"version"} = $1; | ||||
| 843 | } | ||||||
| 844 | 0 | 0 | 0 | if($res =~ / |
|||
| 845 | 0 | 0 | $dbInfo{"lastRecModTime"} = $1; | ||||
| 846 | } | ||||||
| 847 | 0 | 0 | 0 | if($res =~ / |
|||
| 848 | 0 | 0 | $dbInfo{"lastModifiedTime"} = $1; | ||||
| 849 | } | ||||||
| 850 | 0 | 0 | 0 | if($res =~ / |
|||
| 851 | 0 | 0 | $dbInfo{"createdTime"} = $1; | ||||
| 852 | } | ||||||
| 853 | 0 | 0 | 0 | if($res =~ / |
|||
| 854 | 0 | 0 | $dbInfo{"lastAccessTime"} = $1; | ||||
| 855 | } | ||||||
| 856 | 0 | 0 | 0 | if($res =~ / |
|||
| 857 | 0 | 0 | $dbInfo{"numRecords"} = $1; | ||||
| 858 | } | ||||||
| 859 | 0 | 0 | 0 | if($res =~ / |
|||
| 860 | 0 | 0 | $dbInfo{"mgrID"} = $1; | ||||
| 861 | } | ||||||
| 862 | 0 | 0 | 0 | if($res =~ / |
|||
| 863 | 0 | 0 | $dbInfo{"mgrName"} = $1; | ||||
| 864 | } | ||||||
| 865 | 0 | 0 | return %dbInfo; | ||||
| 866 | } | ||||||
| 867 | |||||||
| 868 | sub GetDBPage($$$) | ||||||
| 869 | { | ||||||
| 870 | 0 | 0 | 0 | 0 | my($self, $QuickBaseDBid, $pageid, $pagename) = @_; | ||
| 871 | |||||||
| 872 | 0 | 0 | my $content = " |
||||
| 873 | 0 | 0 | 0 | $content .= " |
|||
| 874 | 0 | 0 | 0 | $content .= " |
|||
| 875 | 0 | 0 | $content .= ""; | ||||
| 876 | |||||||
| 877 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GetDBPage", $content)->content; | ||||
| 878 | } | ||||||
| 879 | |||||||
| 880 | sub GetDBvar($$) | ||||||
| 881 | { | ||||||
| 882 | 0 | 0 | 1 | 0 | my($self,$QuickBaseDBid, $varname) = @_; | ||
| 883 | 0 | 0 | my $content = " |
||||
| 884 | 0 | 0 | my $res = $self->PostAPIURL($QuickBaseDBid, "API_GetDBvar", $content)->content; | ||||
| 885 | 0 | 0 | 0 | if($res =~ / |
|||
| 886 | 0 | 0 | return $1; | ||||
| 887 | } | ||||||
| 888 | else | ||||||
| 889 | { | ||||||
| 890 | 0 | 0 | return ""; | ||||
| 891 | } | ||||||
| 892 | } | ||||||
| 893 | |||||||
| 894 | sub GetNumRecords($) | ||||||
| 895 | { | ||||||
| 896 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid) = @_; | ||
| 897 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_GetNumRecords", "")->content; | ||||
| 898 | 0 | 0 | 0 | if($res =~ / |
|||
| 899 | 0 | 0 | return $1; | ||||
| 900 | } | ||||||
| 901 | else | ||||||
| 902 | { | ||||||
| 903 | 0 | 0 | return ""; | ||||
| 904 | } | ||||||
| 905 | } | ||||||
| 906 | |||||||
| 907 | sub GetOneTimeTicket() | ||||||
| 908 | { | ||||||
| 909 | 0 | 0 | 1 | 0 | my($self) = @_; | ||
| 910 | 0 | 0 | my $res = $self->PostAPIURL ("main", "API_GetOneTimeTicket", "")->content; | ||||
| 911 | 0 | 0 | 0 | if($res =~ / |
|||
| 912 | 0 | 0 | return $1; | ||||
| 913 | } | ||||||
| 914 | else | ||||||
| 915 | { | ||||||
| 916 | 0 | 0 | return ""; | ||||
| 917 | } | ||||||
| 918 | } | ||||||
| 919 | |||||||
| 920 | sub GetRecord($$) | ||||||
| 921 | { | ||||||
| 922 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid, $rid) = @_; | ||
| 923 | 0 | 0 | my $content; | ||||
| 924 | my @record; | ||||||
| 925 | 0 | 0 | my %record; | ||||
| 926 | 0 | 0 | my $true=1; | ||||
| 927 | 0 | 0 | my $false=0; | ||||
| 928 | 0 | 0 | my $isFieldname = $false; | ||||
| 929 | 0 | 0 | my $isFieldvalue = $false; | ||||
| 930 | 0 | 0 | my $isFieldprintable = $false; | ||||
| 931 | 0 | 0 | my ($fieldname, $fieldvalue, $fieldprintable) = ("","",""); | ||||
| 932 | |||||||
| 933 | 0 | 0 | $content = " |
||||
| 934 | " |
||||||
| 935 | ""; | ||||||
| 936 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_GetRecordInfo", $content); | ||||
| 937 | 0 | 0 | my $recordXML = $res->content; | ||||
| 938 | 0 | 0 | $recordXML =~ s/ /\n/ig; |
||||
| 939 | 0 | 0 | @record = $recordXML =~ /<([A-Z\-\.0-9]+)>([^<]*)<\/\1>/isg; | ||||
| 940 | 0 | 0 | my $count = 0; | ||||
| 941 | 0 | 0 | my $record; | ||||
| 942 | |||||||
| 943 | 0 | 0 | foreach $record(@record){ | ||||
| 944 | 0 | 0 | 0 | unless ($count % 2) | |||
| 945 | { | ||||||
| 946 | 0 | 0 | 0 | if($record=~/^name$/) | |||
| 0 | |||||||
| 0 | |||||||
| 947 | { | ||||||
| 948 | 0 | 0 | $isFieldname = $true; | ||||
| 949 | 0 | 0 | 0 | if ($fieldname) | |||
| 950 | { | ||||||
| 951 | 0 | 0 | $fieldname = $self->xml_unescape($fieldname); | ||||
| 952 | 0 | 0 | 0 | if($fieldprintable){ | |||
| 0 | |||||||
| 953 | 0 | 0 | $record{$fieldname} = $self->xml_unescape($fieldprintable); | ||||
| 954 | }elsif($fieldvalue){ | ||||||
| 955 | 0 | 0 | $record{$fieldname} = $self->xml_unescape($fieldvalue); | ||||
| 956 | } | ||||||
| 957 | } | ||||||
| 958 | 0 | 0 | $fieldname=""; $fieldvalue=""; $fieldprintable=""; | ||||
| 0 | 0 | ||||||
| 0 | 0 | ||||||
| 959 | } | ||||||
| 960 | elsif($record=~/^value$/) | ||||||
| 961 | { | ||||||
| 962 | 0 | 0 | $isFieldvalue = $true; | ||||
| 963 | } | ||||||
| 964 | elsif($record=~/^printable$/) | ||||||
| 965 | { | ||||||
| 966 | 0 | 0 | $isFieldprintable = $true; | ||||
| 967 | } | ||||||
| 968 | } | ||||||
| 969 | else | ||||||
| 970 | { | ||||||
| 971 | 0 | 0 | 0 | if($isFieldname) | |||
| 0 | |||||||
| 0 | |||||||
| 972 | { | ||||||
| 973 | 0 | 0 | $fieldname = $record; | ||||
| 974 | 0 | 0 | $isFieldname = $false; | ||||
| 975 | } | ||||||
| 976 | elsif($isFieldvalue) | ||||||
| 977 | { | ||||||
| 978 | 0 | 0 | $fieldvalue = $record; | ||||
| 979 | 0 | 0 | $isFieldvalue = $false; | ||||
| 980 | } | ||||||
| 981 | elsif($isFieldprintable) | ||||||
| 982 | { | ||||||
| 983 | 0 | 0 | $fieldprintable = $record; | ||||
| 984 | 0 | 0 | $isFieldprintable = $false; | ||||
| 985 | } | ||||||
| 986 | } | ||||||
| 987 | 0 | 0 | $count++; | ||||
| 988 | } | ||||||
| 989 | 0 | 0 | 0 | if ($fieldname) | |||
| 990 | { | ||||||
| 991 | 0 | 0 | $fieldname = $self->xml_unescape($fieldname); | ||||
| 992 | 0 | 0 | 0 | if($fieldprintable){ | |||
| 0 | |||||||
| 993 | 0 | 0 | $record{$fieldname} = $self->xml_unescape($fieldprintable); | ||||
| 994 | }elsif($fieldvalue){ | ||||||
| 995 | 0 | 0 | $record{$fieldname} = $self->xml_unescape($fieldvalue); | ||||
| 996 | } | ||||||
| 997 | } | ||||||
| 998 | |||||||
| 999 | 0 | 0 | return %record; | ||||
| 1000 | } | ||||||
| 1001 | |||||||
| 1002 | sub GetRecordAsHTML($$$) | ||||||
| 1003 | { | ||||||
| 1004 | 0 | 0 | 0 | 0 | my($self, $QuickBaseDBid, $rid, $jht) = @_; | ||
| 1005 | 0 | 0 | my $content = " |
||||
| 1006 | 0 | 0 | 0 | $content .= " |
|||
| 1007 | 0 | 0 | $content .= ""; | ||||
| 1008 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GetRecordAsHTML", $content)->content; | ||||
| 1009 | } | ||||||
| 1010 | |||||||
| 1011 | sub GetRecordInfo($$) | ||||||
| 1012 | { | ||||||
| 1013 | 0 | 0 | 0 | 0 | my($self, $QuickBaseDBid, $rid) = @_; | ||
| 1014 | 0 | 0 | my $content = " |
||||
| 1015 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GetRecordInfo", $content)->content; | ||||
| 1016 | } | ||||||
| 1017 | |||||||
| 1018 | sub GetRoleInfo($) | ||||||
| 1019 | { | ||||||
| 1020 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid) = @_; | ||
| 1021 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GetRoleInfo", "")->content; | ||||
| 1022 | } | ||||||
| 1023 | |||||||
| 1024 | sub GetSchema | ||||||
| 1025 | { | ||||||
| 1026 | 0 | 0 | 0 | 0 | my($self,$QuickBaseDBid) = @_; | ||
| 1027 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GetSchema", "")->content; | ||||
| 1028 | } | ||||||
| 1029 | |||||||
| 1030 | sub GetUserInfo($) | ||||||
| 1031 | { | ||||||
| 1032 | 0 | 0 | 1 | 0 | my($self,$email) = @_; | ||
| 1033 | |||||||
| 1034 | 0 | 0 | my $content = " |
||||
| 1035 | |||||||
| 1036 | 0 | 0 | my $res = $self->PostAPIURL ("main", "API_GetUserInfo", $content)->content; | ||||
| 1037 | |||||||
| 1038 | 0 | 0 | my %userInfo; | ||||
| 1039 | 0 | 0 | 0 | if($res =~ / |
|||
| 1040 | 0 | 0 | $userInfo{"login"} = $1 | ||||
| 1041 | } | ||||||
| 1042 | 0 | 0 | 0 | if($res =~ / |
|||
| 1043 | 0 | 0 | $userInfo{"name"} = $1 | ||||
| 1044 | } | ||||||
| 1045 | 0 | 0 | 0 | if($res =~ / |
|||
| 1046 | 0 | 0 | $userInfo{"firstName"} = $1 | ||||
| 1047 | } | ||||||
| 1048 | 0 | 0 | 0 | if($res =~ / |
|||
| 1049 | 0 | 0 | $userInfo{"lastName"} = $1 | ||||
| 1050 | } | ||||||
| 1051 | 0 | 0 | 0 | if($res =~ /id=\"(.*)\"/ ){ | |||
| 1052 | 0 | 0 | $userInfo{"id"} = $1 | ||||
| 1053 | } | ||||||
| 1054 | 0 | 0 | return %userInfo; | ||||
| 1055 | } | ||||||
| 1056 | |||||||
| 1057 | sub GetUserRole($$) | ||||||
| 1058 | { | ||||||
| 1059 | 0 | 0 | 1 | 0 | my($self,$QuickBaseDBid,$userid) = @_; | ||
| 1060 | 0 | 0 | my $content = " |
||||
| 1061 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_GetUserRole", $content)->content; | ||||
| 1062 | } | ||||||
| 1063 | |||||||
| 1064 | sub GrantedDBs() | ||||||
| 1065 | { | ||||||
| 1066 | 0 | 0 | 0 | 0 | my($self) = @_; | ||
| 1067 | 0 | 0 | $self->PostAPIURL ("main", "API_GrantedDBs", "")->content; | ||||
| 1068 | } | ||||||
| 1069 | |||||||
| 1070 | sub ProvisionUser($$$$$) | ||||||
| 1071 | { | ||||||
| 1072 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid,$roleid, $email, $fname, $lname) = @_; | ||
| 1073 | 0 | 0 | my $content = " |
||||
| 1074 | 0 | 0 | $content .= " |
||||
| 1075 | 0 | 0 | $content .= " |
||||
| 1076 | 0 | 0 | $content .= " |
||||
| 1077 | 0 | 0 | $content .= " |
||||
| 1078 | 0 | 0 | $content .= ""; | ||||
| 1079 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseDBid, "API_ProvisionUser", $content)->content; | ||||
| 1080 | 0 | 0 | 0 | if($res =~ / |
|||
| 1081 | 0 | 0 | return $1; | ||||
| 1082 | } | ||||||
| 1083 | else | ||||||
| 1084 | { | ||||||
| 1085 | 0 | 0 | return ""; | ||||
| 1086 | } | ||||||
| 1087 | } | ||||||
| 1088 | |||||||
| 1089 | sub RemoveUserFromRole($$$) | ||||||
| 1090 | { | ||||||
| 1091 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid, $userid, $roleid) = @_; | ||
| 1092 | 0 | 0 | my $content = " |
||||
| 1093 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_RemoveUserFromRole", $content); | ||||
| 1094 | 0 | 0 | return ""; | ||||
| 1095 | } | ||||||
| 1096 | |||||||
| 1097 | sub RenameApp($$) | ||||||
| 1098 | { | ||||||
| 1099 | 0 | 0 | 1 | 0 | my($self,$QuickBaseDBid,$newappname) = @_; | ||
| 1100 | 0 | 0 | my $content = " |
||||
| 1101 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_RenameApp", $content); | ||||
| 1102 | 0 | 0 | return ""; | ||||
| 1103 | } | ||||||
| 1104 | |||||||
| 1105 | sub SendInvitation($$) | ||||||
| 1106 | { | ||||||
| 1107 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid, $userid) = @_; | ||
| 1108 | 0 | 0 | my $content = " |
||||
| 1109 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_SendInvitation", $content); | ||||
| 1110 | 0 | 0 | return ""; | ||||
| 1111 | } | ||||||
| 1112 | |||||||
| 1113 | sub SetDBvar($$$) | ||||||
| 1114 | { | ||||||
| 1115 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid, $varname, $value) = @_; | ||
| 1116 | 0 | 0 | my $content = " |
||||
| 1117 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_SetDBvar", $content); | ||||
| 1118 | 0 | 0 | return ""; | ||||
| 1119 | } | ||||||
| 1120 | |||||||
| 1121 | sub UserRoles($) | ||||||
| 1122 | { | ||||||
| 1123 | 0 | 0 | 1 | 0 | my($self,$QuickBaseDBid) = @_; | ||
| 1124 | 0 | 0 | $self->PostAPIURL ($QuickBaseDBid, "API_UserRoles", "")->content; | ||||
| 1125 | } | ||||||
| 1126 | |||||||
| 1127 | sub GetURL($$) | ||||||
| 1128 | { | ||||||
| 1129 | 0 | 0 | 0 | 0 | my($self, $QuickBaseDBid, $action) = @_; | ||
| 1130 | 0 | 0 | my $error; | ||||
| 1131 | |||||||
| 1132 | 0 | 0 | 0 | unless( $action =~ /^act=API_|\&act=API_/i) | |||
| 1133 | { | ||||||
| 1134 | 0 | 0 | $self->{'error'} = "1"; | ||||
| 1135 | 0 | 0 | $self->{'errortext'} = "Error: You're using a QuickBase URL that is not part of the HTTP API. ". $action . "\n" | ||||
| 1136 | . "Please use only actions that start with 'API_' i.e. act=API_GetNumRecords.\n" | ||||||
| 1137 | . "Please refer to the QuickBase HTTP API documentation."; | ||||||
| 1138 | 0 | 0 | return $self->{'errortext'}; | ||||
| 1139 | } | ||||||
| 1140 | |||||||
| 1141 | |||||||
| 1142 | 0 | 0 | my $ua = new LWP::UserAgent; | ||||
| 1143 | 0 | 0 | $ua->agent("QuickBasePerlAPI/2.0"); | ||||
| 1144 | 0 | 0 | 0 | if ($self->{'proxy'}){ | |||
| 1145 | 0 | 0 | $ua->proxy(['http','https'], $self->{'proxy'}); | ||||
| 1146 | } | ||||||
| 1147 | 0 | 0 | my $req = new HTTP::Request; | ||||
| 1148 | 0 | 0 | $req->method("GET"); | ||||
| 1149 | 0 | 0 | $req->uri($self->URLprefix()."/$QuickBaseDBid?$action"); | ||||
| 1150 | 0 | 0 | 0 | unless ($self->{'ticket'}) | |||
| 1151 | { | ||||||
| 1152 | 0 | 0 | $self->{'ticket'}=$self->getTicket($self->{'username'},$self->{'password'}); | ||||
| 1153 | } | ||||||
| 1154 | 0 | 0 | $req->header('Cookie' => "TICKET=$self->{'ticket'};"); | ||||
| 1155 | 0 | 0 | $req->header('Accept' => 'text/html'); | ||||
| 1156 | # send request | ||||||
| 1157 | 0 | 0 | my $res = $ua->request($req); | ||||
| 1158 | |||||||
| 1159 | |||||||
| 1160 | # check the outcome | ||||||
| 1161 | 0 | 0 | 0 | if ($res->is_error) { | |||
| 1162 | 0 | 0 | $self->{'error'} = $res->code; | ||||
| 1163 | 0 | 0 | $self->{'errortext'} =$res->message; | ||||
| 1164 | 0 | 0 | return "Error: " . $res->code . " " . $res->message; | ||||
| 1165 | } | ||||||
| 1166 | 0 | 0 | return $res->content; | ||||
| 1167 | } | ||||||
| 1168 | |||||||
| 1169 | sub GetFile($$$$) | ||||||
| 1170 | { | ||||||
| 1171 | 0 | 0 | 1 | 0 | my($self, $QuickBaseDBid, $filename, $rid, $fid) = @_; | ||
| 1172 | 0 | 0 | my $error; | ||||
| 1173 | 0 | 0 | my $prefix= $self->URLprefix(); | ||||
| 1174 | 0 | 0 | $prefix =~ s/\/db$/\/up/; | ||||
| 1175 | 0 | 0 | my $ua = new LWP::UserAgent; | ||||
| 1176 | 0 | 0 | $ua->agent("QuickBasePerlAPI/1.0"); | ||||
| 1177 | 0 | 0 | 0 | if ($self->{'proxy'}){ | |||
| 1178 | 0 | 0 | $ua->proxy(['http','https'], $self->{'proxy'}); | ||||
| 1179 | } | ||||||
| 1180 | 0 | 0 | my $req = new HTTP::Request; | ||||
| 1181 | 0 | 0 | $req->method("GET"); | ||||
| 1182 | |||||||
| 1183 | 0 | 0 | $req->uri($prefix."/$QuickBaseDBid/g/r".$self->encode32($rid)."/e".$self->encode32($fid)."/"); | ||||
| 1184 | |||||||
| 1185 | |||||||
| 1186 | 0 | 0 | 0 | unless ($self->{'ticket'}) | |||
| 1187 | { | ||||||
| 1188 | 0 | 0 | $self->{'ticket'}=$self->getTicket($self->{'username'},$self->{'password'}); | ||||
| 1189 | } | ||||||
| 1190 | 0 | 0 | $req->header('Accept' => '*/*'); | ||||
| 1191 | 0 | 0 | $req->header('Cookie' => "TICKET=$self->{'ticket'};"); | ||||
| 1192 | |||||||
| 1193 | # send request | ||||||
| 1194 | 0 | 0 | my $res = $ua->request($req); | ||||
| 1195 | |||||||
| 1196 | # check the outcome | ||||||
| 1197 | 0 | 0 | 0 | if ($res->is_error) { | |||
| 1198 | 0 | 0 | $self->{'error'} = $res->code; | ||||
| 1199 | 0 | 0 | $self->{'errortext'} =$res->message; | ||||
| 1200 | 0 | 0 | return ("Error: " . $res->code . " " . $res->message, $res->headers); | ||||
| 1201 | } | ||||||
| 1202 | 0 | 0 | return ($res->content, $res->headers); | ||||
| 1203 | } | ||||||
| 1204 | |||||||
| 1205 | sub PostURL($$$$) | ||||||
| 1206 | { | ||||||
| 1207 | 0 | 0 | 0 | 0 | my $self = shift; | ||
| 1208 | 0 | 0 | my $QuickBaseDBid = shift; | ||||
| 1209 | 0 | 0 | my $action = shift; | ||||
| 1210 | 0 | 0 | my $content = shift; | ||||
| 1211 | 0 | 0 | 0 | my $content_type = shift || 'application/x-www-form-urlencoded'; | |||
| 1212 | |||||||
| 1213 | 0 | 0 | my $ua = new LWP::UserAgent; | ||||
| 1214 | 0 | 0 | 0 | if ($self->{'proxy'}){ | |||
| 1215 | 0 | 0 | $ua->proxy(['http','https'], $self->{'proxy'}); | ||||
| 1216 | } | ||||||
| 1217 | 0 | 0 | $ua->agent("QuickBasePerlAPI/1.0"); | ||||
| 1218 | 0 | 0 | my $req = new HTTP::Request; | ||||
| 1219 | 0 | 0 | $req->method("POST"); | ||||
| 1220 | 0 | 0 | $req->uri($self->URLprefix."/$QuickBaseDBid?$action"); | ||||
| 1221 | 0 | 0 | 0 | unless ($self->{'ticket'}) | |||
| 1222 | { | ||||||
| 1223 | 0 | 0 | $self->{'ticket'}=$self->getTicket($self->{'username'},$self->{'password'}); | ||||
| 1224 | } | ||||||
| 1225 | 0 | 0 | $req->header('Cookie' => "TICKET=$self->{'ticket'};"); | ||||
| 1226 | 0 | 0 | $req->content_type($content_type); | ||||
| 1227 | |||||||
| 1228 | #This is where we post the info for the new record | ||||||
| 1229 | |||||||
| 1230 | 0 | 0 | $req->content($content); | ||||
| 1231 | 0 | 0 | my $res = $ua->request($req); | ||||
| 1232 | 0 | 0 | 0 | if($res->is_error()){ | |||
| 1233 | 0 | 0 | $self->{'error'} = $res->code; | ||||
| 1234 | 0 | 0 | $self->{'errortext'} =$res->message; | ||||
| 1235 | 0 | 0 | return $res; | ||||
| 1236 | } | ||||||
| 1237 | 0 | 0 | $res->content =~ / |
||||
| 1238 | 0 | 0 | $self->{'error'} = $1; | ||||
| 1239 | 0 | 0 | $self->{'errortext'} = $2; | ||||
| 1240 | 0 | 0 | 0 | if ($res->content =~ / |
|||
| 1241 | { | ||||||
| 1242 | 0 | 0 | $self->{'errortext'} = $1; | ||||
| 1243 | } | ||||||
| 1244 | 0 | 0 | return $res; | ||||
| 1245 | } | ||||||
| 1246 | |||||||
| 1247 | sub PostAPIURL($$$) | ||||||
| 1248 | { | ||||||
| 1249 | 1 | 1 | 0 | 3 | my($self, $QuickBaseDBid, $action, $content) = @_; | ||
| 1250 | 1 | 8 | my $ua = new LWP::UserAgent; | ||||
| 1251 | 1 | 4737 | $ua->agent("QuickBasePerlAPI/2.0"); | ||||
| 1252 | 1 | 50 | 85 | if ($self->{'proxy'}){ | |||
| 1253 | 0 | 0 | $ua->proxy(['http','https'], $self->{'proxy'}); | ||||
| 1254 | } | ||||||
| 1255 | 1 | 11 | my $req = new HTTP::Request; | ||||
| 1256 | 1 | 73 | $req->method('POST'); | ||||
| 1257 | 1 | 50 | 12 | if($self->{'realmhost'}) | |||
| 1258 | { | ||||||
| 1259 | 0 | 0 | $req->uri($self->URLprefix()."/$QuickBaseDBid?realmhost=$self->{'realmhost'}"); | ||||
| 1260 | } | ||||||
| 1261 | else | ||||||
| 1262 | { | ||||||
| 1263 | 1 | 6 | $req->uri($self->URLprefix()."/$QuickBaseDBid"); | ||||
| 1264 | } | ||||||
| 1265 | |||||||
| 1266 | 1 | 28545 | $req->content_type('text/xml'); | ||||
| 1267 | 1 | 61 | $req->header('QUICKBASE-ACTION' => "$action"); | ||||
| 1268 | |||||||
| 1269 | 1 | 50 | 33 | 98 | if ($self->{'apptoken'} ne "" && $self->{'credentials'} !~ / |
||
| 1270 | { | ||||||
| 1271 | 0 | 0 | $self->{'credentials'} .= " |
||||
| 1272 | } | ||||||
| 1273 | |||||||
| 1274 | 1 | 50 | 0 | 8 | if($content =~ /^ |
||
| 0 | |||||||
| 1275 | { | ||||||
| 1276 | 1 | 9 | $content =~s/^ |
||||
| 1277 | } | ||||||
| 1278 | elsif($content eq "" || !defined($content)) | ||||||
| 1279 | { | ||||||
| 1280 | 0 | 0 | $content =" |
||||
| 1281 | } | ||||||
| 1282 | 1 | 50 | 7 | if($content =~ /^ |
|||
| 1283 | { | ||||||
| 1284 | 1 | 4 | $content = "" . $content; | ||||
| 1285 | } | ||||||
| 1286 | 1 | 2 | my $res; | ||||
| 1287 | 1 | 50 | 5 | if ($self->{'ticket'}) | |||
| 1288 | { | ||||||
| 1289 | 0 | 0 | $req->header('Cookie' => "TICKET=$self->{'ticket'};"); | ||||
| 1290 | } | ||||||
| 1291 | |||||||
| 1292 | 1 | 9 | $req->content($content); | ||||
| 1293 | 1 | 28 | $res = $ua->request($req); | ||||
| 1294 | 1 | 50 | 1226087 | if($res->is_error()){ | |||
| 1295 | 0 | 0 | $self->{'error'} = $res->code; | ||||
| 1296 | 0 | 0 | $self->{'errortext'} =$res->message; | ||||
| 1297 | 0 | 0 | return $res; | ||||
| 1298 | } | ||||||
| 1299 | 1 | 50 | 33 | 23 | if (defined ($res->header('Set-Cookie')) && $res->header('Set-Cookie') =~ /TICKET=(.+?);/) | ||
| 50 | |||||||
| 1300 | { | ||||||
| 1301 | 0 | 0 | $self->{'ticket'} = $1; | ||||
| 1302 | 0 | 0 | $self->{'credentials'} = " |
||||
| 1303 | } | ||||||
| 1304 | elsif ($res->content =~ / |
||||||
| 1305 | { | ||||||
| 1306 | 0 | 0 | $self->{'ticket'} = $1; | ||||
| 1307 | 0 | 0 | $self->{'credentials'} = " |
||||
| 1308 | } | ||||||
| 1309 | |||||||
| 1310 | 1 | 125 | $res->content =~ / |
||||
| 1311 | 1 | 57 | $self->{'error'} = $1; | ||||
| 1312 | 1 | 5 | $self->{'errortext'} = $2; | ||||
| 1313 | 1 | 50 | 6 | if ($res->content =~ / |
|||
| 1314 | { | ||||||
| 1315 | 1 | 20 | $self->{'errortext'} = $1; | ||||
| 1316 | } | ||||||
| 1317 | 1 | 50 | 5 | if($self->{'error'} eq '11') | |||
| 1318 | { | ||||||
| 1319 | 0 | 0 | $self->{'errortext'} .= "\nXML request:\n" . $content; | ||||
| 1320 | } | ||||||
| 1321 | 1 | 644 | return $res; | ||||
| 1322 | } | ||||||
| 1323 | |||||||
| 1324 | sub getoneBaseIDbyName($) | ||||||
| 1325 | { | ||||||
| 1326 | 0 | 0 | 0 | 0 | my ($self, $dbName)= @_; | ||
| 1327 | 0 | 0 | return $self->getIDbyName($dbName); | ||||
| 1328 | } | ||||||
| 1329 | |||||||
| 1330 | sub getIDbyName($) | ||||||
| 1331 | { | ||||||
| 1332 | 1 | 1 | 1 | 9 | my ($self, $dbName)= @_; | ||
| 1333 | 1 | 2 | my $content; | ||||
| 1334 | 1 | 3 | $content = " |
||||
| 1335 | 1 | 5 | my $res = $self->PostAPIURL ("main", "API_FindDBByName", $content); | ||||
| 1336 | |||||||
| 1337 | 1 | 50 | 8 | if($res->content =~ / |
|||
| 1338 | 0 | 0 | return $1; | ||||
| 1339 | } | ||||||
| 1340 | else | ||||||
| 1341 | { | ||||||
| 1342 | 1 | 68 | return ""; | ||||
| 1343 | } | ||||||
| 1344 | } | ||||||
| 1345 | |||||||
| 1346 | sub FindDBByName($) | ||||||
| 1347 | { | ||||||
| 1348 | 0 | 0 | 0 | 0 | my ($self, $dbName)= @_; | ||
| 1349 | 0 | 0 | $self->getIDbyName($dbName); | ||||
| 1350 | } | ||||||
| 1351 | |||||||
| 1352 | sub cloneDatabase ($$$) | ||||||
| 1353 | { | ||||||
| 1354 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID, $Name, $Description)=@_; | ||
| 1355 | 0 | 0 | my $content; | ||||
| 1356 | 0 | 0 | $content = " |
||||
| 1357 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_CloneDatabase", $content); | ||||
| 1358 | 0 | 0 | 0 | if($res->content =~ / |
|||
| 1359 | 0 | 0 | return $1; | ||||
| 1360 | } | ||||||
| 1361 | else | ||||||
| 1362 | { | ||||||
| 1363 | 0 | 0 | return ""; | ||||
| 1364 | } | ||||||
| 1365 | } | ||||||
| 1366 | |||||||
| 1367 | sub createDatabase ($$) | ||||||
| 1368 | { | ||||||
| 1369 | 0 | 0 | 1 | 0 | my ($self, $Name, $Description)=@_; | ||
| 1370 | 0 | 0 | my $content; | ||||
| 1371 | 0 | 0 | $content = " |
||||
| 1372 | 0 | 0 | my $res = $self->PostAPIURL ("main", "API_CreateDatabase", $content); | ||||
| 1373 | 0 | 0 | 0 | if($res->content =~ / |
|||
| 1374 | 0 | 0 | my $dbid = $1; | ||||
| 1375 | 0 | 0 | 0 | if($res->content =~ / |
|||
| 1376 | 0 | 0 | return ($dbid,$1); | ||||
| 1377 | } | ||||||
| 1378 | else | ||||||
| 1379 | { | ||||||
| 1380 | 0 | 0 | return $1; | ||||
| 1381 | } | ||||||
| 1382 | } | ||||||
| 1383 | else | ||||||
| 1384 | { | ||||||
| 1385 | 0 | 0 | return ""; | ||||
| 1386 | } | ||||||
| 1387 | } | ||||||
| 1388 | |||||||
| 1389 | sub addField ($$$$) | ||||||
| 1390 | { | ||||||
| 1391 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID, $label, $type, $mode)=@_; | ||
| 1392 | 0 | 0 | my $content; | ||||
| 1393 | 0 | 0 | $content = " |
||||
| 1394 | 0 | 0 | 0 | if ($mode) | |||
| 1395 | { | ||||||
| 1396 | 0 | 0 | $content .= " |
||||
| 1397 | } | ||||||
| 1398 | else | ||||||
| 1399 | { | ||||||
| 1400 | 0 | 0 | $content .= ""; | ||||
| 1401 | } | ||||||
| 1402 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_AddField", $content); | ||||
| 1403 | 0 | 0 | 0 | if($res->content =~ / |
|||
| 1404 | 0 | 0 | return $1; | ||||
| 1405 | } | ||||||
| 1406 | else | ||||||
| 1407 | { | ||||||
| 1408 | 0 | 0 | return ""; | ||||
| 1409 | } | ||||||
| 1410 | } | ||||||
| 1411 | |||||||
| 1412 | sub deleteField ($$) | ||||||
| 1413 | { | ||||||
| 1414 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID, $fid)=@_; | ||
| 1415 | 0 | 0 | my $content; | ||||
| 1416 | 0 | 0 | $content = " |
||||
| 1417 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_DeleteField", $content); | ||||
| 1418 | } | ||||||
| 1419 | |||||||
| 1420 | sub setFieldProperties ($$%) | ||||||
| 1421 | { | ||||||
| 1422 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID, $fid, %properties)=@_; | ||
| 1423 | 0 | 0 | my $content; | ||||
| 1424 | my $property; | ||||||
| 1425 | 0 | 0 | my $value; | ||||
| 1426 | 0 | 0 | $content = " |
||||
| 1427 | 0 | 0 | foreach $property (keys %properties) | ||||
| 1428 | { | ||||||
| 1429 | 0 | 0 | $content .= "<$property>".$self->xml_escape($properties{$property})."$property>"; | ||||
| 1430 | } | ||||||
| 1431 | 0 | 0 | $content .= ""; | ||||
| 1432 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_SetFieldProperties", $content); | ||||
| 1433 | 0 | 0 | 0 | if($res->content =~ / |
|||
| 1434 | 0 | 0 | return $1; | ||||
| 1435 | } | ||||||
| 1436 | else | ||||||
| 1437 | { | ||||||
| 1438 | 0 | 0 | return ""; | ||||
| 1439 | } | ||||||
| 1440 | } | ||||||
| 1441 | |||||||
| 1442 | |||||||
| 1443 | sub purgeRecords ($$) | ||||||
| 1444 | { | ||||||
| 1445 | 0 | 0 | 0 | 0 | my ($self, $QuickBaseID, $query)=@_; | ||
| 1446 | |||||||
| 1447 | 0 | 0 | my $content; | ||||
| 1448 | 0 | 0 | 0 | if ($query =~ /^\{.*\}$/) | |||
| 0 | |||||||
| 1449 | { | ||||||
| 1450 | 0 | 0 | $content = " |
||||
| 1451 | } | ||||||
| 1452 | elsif ($query =~ /^\d+$/) | ||||||
| 1453 | { | ||||||
| 1454 | 0 | 0 | $content = " |
||||
| 1455 | } | ||||||
| 1456 | else | ||||||
| 1457 | { | ||||||
| 1458 | 0 | 0 | $content = " |
||||
| 1459 | } | ||||||
| 1460 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_PurgeRecords", $content); | ||||
| 1461 | 0 | 0 | 0 | if($res->content =~ / |
|||
| 1462 | 0 | 0 | return $1; | ||||
| 1463 | } | ||||||
| 1464 | else | ||||||
| 1465 | { | ||||||
| 1466 | 0 | 0 | return ""; | ||||
| 1467 | } | ||||||
| 1468 | } | ||||||
| 1469 | |||||||
| 1470 | sub DoQuery ($$$$$) | ||||||
| 1471 | { | ||||||
| 1472 | 0 | 0 | 0 | 0 | my ($self, $QuickBaseID, $query, $clist, $slist, $options)=@_; | ||
| 1473 | 0 | 0 | return $self->doQuery ($QuickBaseID, $query, $clist, $slist, $options); | ||||
| 1474 | } | ||||||
| 1475 | |||||||
| 1476 | sub doQuery ($$$$$) | ||||||
| 1477 | { | ||||||
| 1478 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID, $query, $clist, $slist, $options)=@_; | ||
| 1479 | |||||||
| 1480 | 0 | 0 | my $content; | ||||
| 1481 | my $result; | ||||||
| 1482 | 0 | 0 | my @result; | ||||
| 1483 | 0 | 0 | my $record={}; | ||||
| 1484 | 0 | 0 | my $field; | ||||
| 1485 | my @labels; | ||||||
| 1486 | 0 | 0 | my $fieldvalue; | ||||
| 1487 | 0 | 0 | my $counter = 0; | ||||
| 1488 | 0 | 0 | my $numfields; | ||||
| 1489 | my $i; | ||||||
| 1490 | |||||||
| 1491 | 0 | 0 | 0 | if ($query =~ /^\{.*\}$/) | |||
| 0 | |||||||
| 1492 | { | ||||||
| 1493 | 0 | 0 | $content = " |
||||
| 1494 | } | ||||||
| 1495 | elsif ($query =~ /^\d+$/) | ||||||
| 1496 | { | ||||||
| 1497 | 0 | 0 | $content = " |
||||
| 1498 | } | ||||||
| 1499 | else | ||||||
| 1500 | { | ||||||
| 1501 | 0 | 0 | $content = " |
||||
| 1502 | } | ||||||
| 1503 | |||||||
| 1504 | 0 | 0 | $content .= " |
||||
| 1505 | 0 | 0 | $result = $self->PostAPIURL ($QuickBaseID, "API_DoQuery", $content)->content; | ||||
| 1506 | 0 | 0 | @labels = $result =~ / | ||||
| 1507 | 0 | 0 | $numfields = @labels; | ||||
| 1508 | 0 | 0 | for $i (0 .. $numfields) | ||||
| 1509 | { | ||||||
| 1510 | 0 | 0 | $labels[$i] = $self->xml_unescape($labels[$i]); | ||||
| 1511 | } | ||||||
| 1512 | 0 | 0 | foreach $fieldvalue ( $result =~ / |
||||
| 1513 | { | ||||||
| 1514 | 0 | 0 | 0 | unless ($counter % $numfields) | |||
| 1515 | { | ||||||
| 1516 | 0 | 0 | 0 | if ($counter > 0) | |||
| 1517 | { | ||||||
| 1518 | 0 | 0 | push (@result, $record); | ||||
| 1519 | } | ||||||
| 1520 | 0 | 0 | $record={}; | ||||
| 1521 | } | ||||||
| 1522 | 0 | 0 | $record->{$labels[$counter % $numfields]}=$self->xml_unescape($fieldvalue); | ||||
| 1523 | 0 | 0 | $counter++; | ||||
| 1524 | } | ||||||
| 1525 | 0 | 0 | 0 | if ($counter) | |||
| 1526 | { | ||||||
| 1527 | 0 | 0 | push (@result, $record); | ||||
| 1528 | } | ||||||
| 1529 | 0 | 0 | return @result; | ||||
| 1530 | } | ||||||
| 1531 | |||||||
| 1532 | sub getCompleteCSV ($) | ||||||
| 1533 | { | ||||||
| 1534 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID)=@_; | ||
| 1535 | 0 | 0 | my $content; | ||||
| 1536 | 0 | 0 | my $clist=""; | ||||
| 1537 | 0 | 0 | my $fid; | ||||
| 1538 | my @ids; | ||||||
| 1539 | 0 | 0 | my $result; | ||||
| 1540 | 0 | 0 | $result = $self->PostAPIURL ($QuickBaseID, "API_GetSchema", " |
||||
| 1541 | 0 | 0 | @ids = $result =~ / |
||||
| 1542 | 0 | 0 | foreach $fid (@ids){ | ||||
| 1543 | 0 | 0 | $clist .= "$fid."; | ||||
| 1544 | } | ||||||
| 1545 | 0 | 0 | $content .= " |
||||
| 1546 | 0 | 0 | return $self->PostAPIURL ($QuickBaseID, "API_GenResultsTable", $content)->content; | ||||
| 1547 | } | ||||||
| 1548 | |||||||
| 1549 | sub GetRIDs ($) | ||||||
| 1550 | { | ||||||
| 1551 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID) = @_; | ||
| 1552 | 0 | 0 | my $content=" |
||||
| 1553 | 0 | 0 | my $fid; | ||||
| 1554 | 0 | 0 | $self->PostAPIURL($QuickBaseID,"API_GetSchema",$content)->content =~ / | ||||
| 1555 | 0 | 0 | $fid = $1; | ||||
| 1556 | 0 | 0 | $content = " |
||||
| 1557 | 0 | 0 | my @rids = $self->PostAPIURL($QuickBaseID,"API_DoQuery",$content)->content =~ / |
||||
| 1558 | 0 | 0 | return @rids; | ||||
| 1559 | } | ||||||
| 1560 | |||||||
| 1561 | sub EditRecord ($$%) | ||||||
| 1562 | { | ||||||
| 1563 | 0 | 0 | 1 | 0 | my ($self, $QuickBaseID, $rid, %recorddata) = @_; | ||
| 1564 | 0 | 0 | my $name; | ||||
| 1565 | 0 | 0 | my $content = " |
||||
| 1566 | 0 | 0 | my $tag; | ||||
| 1567 | |||||||
| 1568 | 0 | 0 | foreach $name (keys(%recorddata)) | ||||
| 1569 | { | ||||||
| 1570 | 0 | 0 | $tag=$name; | ||||
| 1571 | 0 | 0 | $tag =~tr/A-Z/a-z/; | ||||
| 1572 | 0 | 0 | $tag=~s/[^a-z0-9]/_/g; | ||||
| 1573 | 0 | 0 | $content .= $self->createFieldXML($tag, $recorddata{$name}); | ||||
| 1574 | } | ||||||
| 1575 | 0 | 0 | $content .= ""; | ||||
| 1576 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_EditRecord", $content); | ||||
| 1577 | 0 | 0 | return $res->content; | ||||
| 1578 | } | ||||||
| 1579 | |||||||
| 1580 | sub EditRecordWithUpdateID ($$$%) | ||||||
| 1581 | { | ||||||
| 1582 | 0 | 0 | 0 | 0 | my ($self, $QuickBaseID, $rid, $update_id, %recorddata) = @_; | ||
| 1583 | 0 | 0 | my $name; | ||||
| 1584 | 0 | 0 | my $content = " |
||||
| 1585 | 0 | 0 | my ($value, $tag); | ||||
| 1586 | 0 | 0 | $content .= " |
||||
| 1587 | |||||||
| 1588 | |||||||
| 1589 | 0 | 0 | foreach $name (keys(%recorddata)) | ||||
| 1590 | { | ||||||
| 1591 | 0 | 0 | $value = $recorddata{$name}; | ||||
| 1592 | 0 | 0 | $value = $self->xml_escape($value); | ||||
| 1593 | 0 | 0 | $tag=$name; | ||||
| 1594 | 0 | 0 | $tag =~tr/A-Z/a-z/; | ||||
| 1595 | 0 | 0 | $tag=~s/[^a-z0-9]/_/g; | ||||
| 1596 | |||||||
| 1597 | 0 | 0 | $content .= $self->createFieldXML($tag, $recorddata{$name}); | ||||
| 1598 | } | ||||||
| 1599 | |||||||
| 1600 | 0 | 0 | $content .= ""; | ||||
| 1601 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_EditRecord", $content); | ||||
| 1602 | 0 | 0 | return $res->content; | ||||
| 1603 | } | ||||||
| 1604 | |||||||
| 1605 | |||||||
| 1606 | sub ImportFromCSV ($$$$) | ||||||
| 1607 | { | ||||||
| 1608 | 0 | 0 | 0 | 0 | my ($self, $QuickBaseID, $CSVData, $clist, $skipfirst) = @_; | ||
| 1609 | 0 | 0 | my $content = " |
||||
| 1610 | |||||||
| 1611 | 0 | 0 | $content .= " |
||||
| 1612 | 0 | 0 | 0 | if($skipfirst) | |||
| 1613 | { | ||||||
| 1614 | 0 | 0 | $content .= " |
||||
| 1615 | } | ||||||
| 1616 | 0 | 0 | $content .= ""; | ||||
| 1617 | 0 | 0 | my $res = $self->PostAPIURL ($QuickBaseID, "API_ImportFromCSV", $content); | ||||
| 1618 | 0 | 0 | return $res->content; | ||||
| 1619 | } | ||||||
| 1620 | |||||||
| 1621 | |||||||
| 1622 | sub GetNextField ($$$$) | ||||||
| 1623 | { | ||||||
| 1624 | 0 | 0 | 0 | 0 | my ($self, $datapointer, $delim, $offsetpointer, $fieldpointer)=@_; | ||
| 1625 | 0 | 0 | my $BEFORE_FIELD=0; | ||||
| 1626 | 0 | 0 | my $IN_QUOTED_FIELD=1; | ||||
| 1627 | 0 | 0 | my $IN_UNQUOTED_FIELD=2; | ||||
| 1628 | 0 | 0 | my $DOUBLE_QUOTE_TEST=3; | ||||
| 1629 | 0 | 0 | my $c=""; | ||||
| 1630 | 0 | 0 | my $state = $BEFORE_FIELD; | ||||
| 1631 | 0 | 0 | my $p = $$offsetpointer; | ||||
| 1632 | 0 | 0 | my $endofdata = length($$datapointer); | ||||
| 1633 | 0 | 0 | my $false=0; | ||||
| 1634 | 0 | 0 | my $true=1; | ||||
| 1635 | |||||||
| 1636 | |||||||
| 1637 | 0 | 0 | $$fieldpointer = ""; | ||||
| 1638 | |||||||
| 1639 | 0 | 0 | while ($true) | ||||
| 1640 | { | ||||||
| 1641 | 0 | 0 | 0 | if ($p >= $endofdata) | |||
| 1642 | { | ||||||
| 1643 | # File, line and field are done | ||||||
| 1644 | 0 | 0 | $$offsetpointer = $p; | ||||
| 1645 | 0 | 0 | return $false; | ||||
| 1646 | } | ||||||
| 1647 | |||||||
| 1648 | 0 | 0 | $c = substr($$datapointer, $p, 1); | ||||
| 1649 | |||||||
| 1650 | 0 | 0 | 0 | if($state == $DOUBLE_QUOTE_TEST) | |||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 1651 | { | ||||||
| 1652 | # These checks are ordered by likelihood */ | ||||||
| 1653 | 0 | 0 | 0 | 0 | if ($c eq $delim) | ||
| 0 | |||||||
| 0 | |||||||
| 1654 | { | ||||||
| 1655 | # Field is done; delimiter means more to come | ||||||
| 1656 | 0 | 0 | $$offsetpointer = $p + 1; | ||||
| 1657 | 0 | 0 | return $true; | ||||
| 1658 | } | ||||||
| 1659 | elsif ($c eq "\n" || $c eq "\r") | ||||||
| 1660 | { | ||||||
| 1661 | # Line and field are done | ||||||
| 1662 | 0 | 0 | $$offsetpointer = $p + 1; | ||||
| 1663 | 0 | 0 | return $false; | ||||
| 1664 | } | ||||||
| 1665 | elsif ($c eq '"') | ||||||
| 1666 | { | ||||||
| 1667 | # It is doubled, so append one quote | ||||||
| 1668 | 0 | 0 | $$fieldpointer .= '"'; | ||||
| 1669 | 0 | 0 | $p++; | ||||
| 1670 | 0 | 0 | $state = $IN_QUOTED_FIELD; | ||||
| 1671 | } | ||||||
| 1672 | else | ||||||
| 1673 | { | ||||||
| 1674 | # !!! Shouldn't have anything else after an end quote! | ||||||
| 1675 | # But do something reasonable to recover: go into unquoted mode | ||||||
| 1676 | 0 | 0 | $$fieldpointer .= $c; | ||||
| 1677 | 0 | 0 | $p++; | ||||
| 1678 | 0 | 0 | $state = $IN_UNQUOTED_FIELD; | ||||
| 1679 | } | ||||||
| 1680 | } | ||||||
| 1681 | elsif($state == $BEFORE_FIELD) | ||||||
| 1682 | { | ||||||
| 1683 | # These checks are ordered by likelihood */ | ||||||
| 1684 | 0 | 0 | 0 | 0 | if ($c eq $delim) | ||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 1685 | { | ||||||
| 1686 | # Field is blank; delimiter means more to come | ||||||
| 1687 | 0 | 0 | $$offsetpointer = $p + 1; | ||||
| 1688 | 0 | 0 | return $true; | ||||
| 1689 | } | ||||||
| 1690 | elsif ($c eq '"') | ||||||
| 1691 | { | ||||||
| 1692 | # Found the beginning of a quoted field | ||||||
| 1693 | 0 | 0 | $p++; | ||||
| 1694 | 0 | 0 | $state = $IN_QUOTED_FIELD; | ||||
| 1695 | } | ||||||
| 1696 | elsif ($c eq "\n" || $c eq "\r") | ||||||
| 1697 | { | ||||||
| 1698 | # Field is blank and line is done | ||||||
| 1699 | 0 | 0 | $$offsetpointer = $p + 1; | ||||
| 1700 | 0 | 0 | return $false; | ||||
| 1701 | } | ||||||
| 1702 | elsif ($c eq ' ') | ||||||
| 1703 | { | ||||||
| 1704 | # Ignore leading spaces | ||||||
| 1705 | 0 | 0 | $p++; | ||||
| 1706 | } | ||||||
| 1707 | else | ||||||
| 1708 | { | ||||||
| 1709 | # Found some other character, beginning an unquoted field | ||||||
| 1710 | 0 | 0 | $$fieldpointer.=$c; | ||||
| 1711 | 0 | 0 | $p++; | ||||
| 1712 | 0 | 0 | $state = $IN_UNQUOTED_FIELD; | ||||
| 1713 | } | ||||||
| 1714 | } | ||||||
| 1715 | elsif ($state == $IN_UNQUOTED_FIELD) | ||||||
| 1716 | { | ||||||
| 1717 | # These checks are ordered by likelihood */ | ||||||
| 1718 | 0 | 0 | 0 | 0 | if ($c eq $delim) | ||
| 0 | |||||||
| 1719 | { | ||||||
| 1720 | # Field is done; delimiter means more to come | ||||||
| 1721 | 0 | 0 | $$offsetpointer = $p + 1; | ||||
| 1722 | 0 | 0 | return $true; | ||||
| 1723 | } | ||||||
| 1724 | elsif ($c eq "\n" || $c eq "\r") | ||||||
| 1725 | { | ||||||
| 1726 | # Line and field are done | ||||||
| 1727 | 0 | 0 | $$offsetpointer = $p + 1; | ||||
| 1728 | 0 | 0 | return $false; | ||||
| 1729 | } | ||||||
| 1730 | else | ||||||
| 1731 | { | ||||||
| 1732 | # Found some other character, add it to the field | ||||||
| 1733 | 0 | 0 | $$fieldpointer.=$c; | ||||
| 1734 | 0 | 0 | $p++; | ||||
| 1735 | } | ||||||
| 1736 | } | ||||||
| 1737 | elsif($state == $IN_QUOTED_FIELD) | ||||||
| 1738 | { | ||||||
| 1739 | 0 | 0 | 0 | if ($c eq '"') | |||
| 1740 | { | ||||||
| 1741 | 0 | 0 | $p++; | ||||
| 1742 | 0 | 0 | $state = $DOUBLE_QUOTE_TEST; | ||||
| 1743 | } | ||||||
| 1744 | else | ||||||
| 1745 | { | ||||||
| 1746 | # Found some other character, add it to the field | ||||||
| 1747 | 0 | 0 | $$fieldpointer.=$c; | ||||
| 1748 | 0 | 0 | $p++; | ||||
| 1749 | } | ||||||
| 1750 | } | ||||||
| 1751 | } | ||||||
| 1752 | } | ||||||
| 1753 | |||||||
| 1754 | sub GetNextLine ($$$$$$) | ||||||
| 1755 | { | ||||||
| 1756 | 0 | 0 | 0 | 0 | my ($self, $data, $delim, $offsetpointer, $fieldpointer, $line, $lineIsEmptyPtr)=@_; | ||
| 1757 | 0 | 0 | my $false=0; | ||||
| 1758 | 0 | 0 | my $true=1; | ||||
| 1759 | |||||||
| 1760 | 0 | 0 | undef(@$line); | ||||
| 1761 | # skip any empty lines | ||||||
| 1762 | 0 | 0 | 0 | while ($$offsetpointer < length($$data) && ((substr($$data, $$offsetpointer, 1) eq "\r") || (substr($$data, $$offsetpointer, 1) eq "\n"))) | |||
| 0 | |||||||
| 1763 | { | ||||||
| 1764 | 0 | 0 | $$offsetpointer++; | ||||
| 1765 | } | ||||||
| 1766 | |||||||
| 1767 | 0 | 0 | 0 | if ($$offsetpointer >= length($$data)) | |||
| 1768 | { | ||||||
| 1769 | 0 | 0 | return $false; | ||||
| 1770 | } | ||||||
| 1771 | |||||||
| 1772 | 0 | 0 | $$lineIsEmptyPtr = $true; | ||||
| 1773 | 0 | 0 | my $moreToCome; | ||||
| 1774 | 0 | 0 | do { | ||||
| 1775 | 0 | 0 | $moreToCome = $self->GetNextField ($data, $delim, $offsetpointer, $fieldpointer); | ||||
| 1776 | 0 | 0 | push (@$line, $$fieldpointer); | ||||
| 1777 | 0 | 0 | 0 | if ($$fieldpointer) | |||
| 1778 | { | ||||||
| 1779 | 0 | 0 | $$lineIsEmptyPtr = $false; | ||||
| 1780 | } | ||||||
| 1781 | } | ||||||
| 1782 | while ($moreToCome); | ||||||
| 1783 | |||||||
| 1784 | 0 | 0 | return $true; | ||||
| 1785 | } | ||||||
| 1786 | |||||||
| 1787 | |||||||
| 1788 | sub ParseDelimited ($$) | ||||||
| 1789 | { | ||||||
| 1790 | 0 | 0 | 0 | 0 | my ($self, $data, $delim)=@_; | ||
| 1791 | 0 | 0 | my @output; | ||||
| 1792 | my @line; | ||||||
| 1793 | 0 | 0 | my $offset =0; | ||||
| 1794 | |||||||
| 1795 | 0 | 0 | my $field=""; | ||||
| 1796 | 0 | 0 | my $lineEmpty=1; | ||||
| 1797 | 0 | 0 | my $maxsize = 0; | ||||
| 1798 | 0 | 0 | my $numfields=0; | ||||
| 1799 | 0 | 0 | my $i; | ||||
| 1800 | |||||||
| 1801 | # Parse lines until the eof is hit | ||||||
| 1802 | 0 | 0 | while ($self->GetNextLine (\$data, $delim, \$offset, \$field, \@line, \$lineEmpty)) | ||||
| 1803 | { | ||||||
| 1804 | 0 | 0 | 0 | unless($lineEmpty) | |||
| 1805 | { | ||||||
| 1806 | 0 | 0 | push (@output, [@line]); | ||||
| 1807 | 0 | 0 | $numfields=@line; | ||||
| 1808 | 0 | 0 | 0 | if ($numfields > $maxsize) | |||
| 1809 | { | ||||||
| 1810 | 0 | 0 | $maxsize = $numfields; | ||||
| 1811 | } | ||||||
| 1812 | } | ||||||
| 1813 | } | ||||||
| 1814 | |||||||
| 1815 | |||||||
| 1816 | # If there are any lines which are shorter than the longest | ||||||
| 1817 | # lines, fill them out with "" entries here. This simplifies | ||||||
| 1818 | # checking later. | ||||||
| 1819 | 0 | 0 | foreach $i(@output) | ||||
| 1820 | { | ||||||
| 1821 | 0 | 0 | while (@$i < $maxsize) | ||||
| 1822 | { | ||||||
| 1823 | 0 | 0 | push (@$i, ""); | ||||
| 1824 | } | ||||||
| 1825 | } | ||||||
| 1826 | |||||||
| 1827 | 0 | 0 | return @output; | ||||
| 1828 | |||||||
| 1829 | } | ||||||
| 1830 | sub xml_escape ($) { | ||||||
| 1831 | 3 | 3 | 0 | 5 | my ($self, $rest) = @_; | ||
| 1832 | 3 | 50 | 7 | unless(defined($rest)){return "";} | |||
| 0 | 0 | ||||||
| 1833 | 3 | 8 | $rest =~ s/&/&/g; | ||||
| 1834 | 3 | 4 | $rest =~ s/</g; | ||||
| 1835 | 3 | 6 | $rest =~ s/>/>/g; | ||||
| 1836 | 3 | 6 | $rest =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()# ])/$XMLescapes{$1}/g; | ||||
| 1837 | 3 | 9 | return $rest; | ||||
| 1838 | } | ||||||
| 1839 | |||||||
| 1840 | sub xml_unescape ($) { | ||||||
| 1841 | 0 | 0 | 0 | my ($self, $rest) = @_; | |||
| 1842 | 0 | 0 | unless(defined($rest)){return "";} | ||||
| 0 | |||||||
| 1843 | 0 | $rest =~ s/ /\n/ig; |
|||||
| 1844 | 0 | $rest =~ s/</ | |||||
| 1845 | 0 | $rest =~ s/>/>/g; | |||||
| 1846 | 0 | $rest =~ s/&/&/g; | |||||
| 1847 | 0 | $rest =~ s/'/'/g; | |||||
| 1848 | 0 | $rest =~ s/"/"/g; | |||||
| 1849 | 0 | $rest =~ s/([0-9]{2,3});/chr($1)/eg; | |||||
| 0 | |||||||
| 1850 | 0 | return $rest; | |||||
| 1851 | } | ||||||
| 1852 | |||||||
| 1853 | sub encode32 ($){ | ||||||
| 1854 | 0 | 0 | 0 | my ($self, $number) = @_; | |||
| 1855 | 0 | my $result = ""; | |||||
| 1856 | 0 | while ($number > 0){ | |||||
| 1857 | 0 | my $remainder = $number % 32; | |||||
| 1858 | 0 | $number = ($number - $remainder)/32; | |||||
| 1859 | 0 | $result = $self->hash32($remainder) . $result; | |||||
| 1860 | } | ||||||
| 1861 | 0 | return $result; | |||||
| 1862 | } | ||||||
| 1863 | |||||||
| 1864 | sub hash32 ($){ | ||||||
| 1865 | 0 | 0 | 0 | my ($self, $number) = @_; | |||
| 1866 | 0 | 0 | if($number == 0) {return 'a';} | ||||
| 0 | |||||||
| 1867 | 0 | 0 | if($number == 1) {return 'b';} | ||||
| 0 | |||||||
| 1868 | 0 | 0 | if($number == 2) {return 'c';} | ||||
| 0 | |||||||
| 1869 | 0 | 0 | if($number == 3) {return 'd';} | ||||
| 0 | |||||||
| 1870 | 0 | 0 | if($number == 4) {return 'e';} | ||||
| 0 | |||||||
| 1871 | 0 | 0 | if($number == 5) {return 'f';} | ||||
| 0 | |||||||
| 1872 | 0 | 0 | if($number == 6) {return 'g';} | ||||
| 0 | |||||||
| 1873 | 0 | 0 | if($number == 7) {return 'h';} | ||||
| 0 | |||||||
| 1874 | 0 | 0 | if($number == 8) {return 'i';} | ||||
| 0 | |||||||
| 1875 | 0 | 0 | if($number == 9) {return 'j';} | ||||
| 0 | |||||||
| 1876 | 0 | 0 | if($number == 10) {return 'k';} | ||||
| 0 | |||||||
| 1877 | 0 | 0 | if($number == 11) {return 'm';} | ||||
| 0 | |||||||
| 1878 | 0 | 0 | if($number == 12) {return 'n';} | ||||
| 0 | |||||||
| 1879 | 0 | 0 | if($number == 13) {return 'p';} | ||||
| 0 | |||||||
| 1880 | 0 | 0 | if($number == 14) {return 'q';} | ||||
| 0 | |||||||
| 1881 | 0 | 0 | if($number == 15) {return 'r';} | ||||
| 0 | |||||||
| 1882 | 0 | 0 | if($number == 16) {return 's';} | ||||
| 0 | |||||||
| 1883 | 0 | 0 | if($number == 17) {return 't';} | ||||
| 0 | |||||||
| 1884 | 0 | 0 | if($number == 18) {return 'u';} | ||||
| 0 | |||||||
| 1885 | 0 | 0 | if($number == 19) {return 'v';} | ||||
| 0 | |||||||
| 1886 | 0 | 0 | if($number == 20) {return 'w';} | ||||
| 0 | |||||||
| 1887 | 0 | 0 | if($number == 21) {return 'x';} | ||||
| 0 | |||||||
| 1888 | 0 | 0 | if($number == 22) {return 'y';} | ||||
| 0 | |||||||
| 1889 | 0 | 0 | if($number == 23) {return 'z';} | ||||
| 0 | |||||||
| 1890 | 0 | 0 | if($number == 24) {return '2';} | ||||
| 0 | |||||||
| 1891 | 0 | 0 | if($number == 25) {return '3';} | ||||
| 0 | |||||||
| 1892 | 0 | 0 | if($number == 26) {return '4';} | ||||
| 0 | |||||||
| 1893 | 0 | 0 | if($number == 27) {return '5';} | ||||
| 0 | |||||||
| 1894 | 0 | 0 | if($number == 28) {return '6';} | ||||
| 0 | |||||||
| 1895 | 0 | 0 | if($number == 29) {return '7';} | ||||
| 0 | |||||||
| 1896 | 0 | 0 | if($number == 30) {return '8';} | ||||
| 0 | |||||||
| 1897 | 0 | 0 | if($number == 31) {return '9';} | ||||
| 0 | |||||||
| 1898 | } | ||||||
| 1899 | |||||||
| 1900 | |||||||
| 1901 | |||||||
| 1902 | sub unencode32 ($){ | ||||||
| 1903 | 0 | 0 | 0 | my ($self, $number) = @_; | |||
| 1904 | 0 | my $result = 0; | |||||
| 1905 | 0 | while ($number ne ""){ | |||||
| 1906 | 0 | my $l = length($number); | |||||
| 1907 | 0 | my $firstchar = substr($number, 0, 1); | |||||
| 1908 | 0 | $result = ($result * 32) + $self->unhash32($firstchar); | |||||
| 1909 | 0 | $number = substr($number, 1, $l-1); | |||||
| 1910 | } | ||||||
| 1911 | 0 | return $result; | |||||
| 1912 | } | ||||||
| 1913 | |||||||
| 1914 | |||||||
| 1915 | |||||||
| 1916 | sub unhash32 ($) { | ||||||
| 1917 | 0 | 0 | 0 | my ($self, $number) = @_; | |||
| 1918 | 0 | 0 | if($number eq 'a') {return 0;} | ||||
| 0 | |||||||
| 1919 | 0 | 0 | if($number eq 'b') {return 1;} | ||||
| 0 | |||||||
| 1920 | 0 | 0 | if($number eq 'c') {return 2;} | ||||
| 0 | |||||||
| 1921 | 0 | 0 | if($number eq 'd') {return 3;} | ||||
| 0 | |||||||
| 1922 | 0 | 0 | if($number eq 'e') {return 4;} | ||||
| 0 | |||||||
| 1923 | 0 | 0 | if($number eq 'f') {return 5;} | ||||
| 0 | |||||||
| 1924 | 0 | 0 | if($number eq 'g') {return 6;} | ||||
| 0 | |||||||
| 1925 | 0 | 0 | if($number eq 'h') {return 7;} | ||||
| 0 | |||||||
| 1926 | 0 | 0 | if($number eq 'i') {return 8;} | ||||
| 0 | |||||||
| 1927 | 0 | 0 | if($number eq 'j') {return 9;} | ||||
| 0 | |||||||
| 1928 | 0 | 0 | if($number eq 'k') {return 10;} | ||||
| 0 | |||||||
| 1929 | 0 | 0 | if($number eq 'm') {return 11;} | ||||
| 0 | |||||||
| 1930 | 0 | 0 | if($number eq 'n') {return 12;} | ||||
| 0 | |||||||
| 1931 | 0 | 0 | if($number eq 'p') {return 13;} | ||||
| 0 | |||||||
| 1932 | 0 | 0 | if($number eq 'q') {return 14;} | ||||
| 0 | |||||||
| 1933 | 0 | 0 | if($number eq 'r') {return 15;} | ||||
| 0 | |||||||
| 1934 | 0 | 0 | if($number eq 's') {return 16;} | ||||
| 0 | |||||||
| 1935 | 0 | 0 | if($number eq 't') {return 17;} | ||||
| 0 | |||||||
| 1936 | 0 | 0 | if($number eq 'u') {return 18;} | ||||
| 0 | |||||||
| 1937 | 0 | 0 | if($number eq 'v') {return 19;} | ||||
| 0 | |||||||
| 1938 | 0 | 0 | if($number eq 'w') {return 20;} | ||||
| 0 | |||||||
| 1939 | 0 | 0 | if($number eq 'x') {return 21;} | ||||
| 0 | |||||||
| 1940 | 0 | 0 | if($number eq 'y') {return 22;} | ||||
| 0 | |||||||
| 1941 | 0 | 0 | if($number eq 'z') {return 23;} | ||||
| 0 | |||||||
| 1942 | 0 | 0 | if($number eq '2') {return 24;} | ||||
| 0 | |||||||
| 1943 | 0 | 0 | if($number eq '3') {return 25;} | ||||
| 0 | |||||||
| 1944 | 0 | 0 | if($number eq '4') {return 26;} | ||||
| 0 | |||||||
| 1945 | 0 | 0 | if($number eq '5') {return 27;} | ||||
| 0 | |||||||
| 1946 | 0 | 0 | if($number eq '6') {return 28;} | ||||
| 0 | |||||||
| 1947 | 0 | 0 | if($number eq '7') {return 29;} | ||||
| 0 | |||||||
| 1948 | 0 | 0 | if($number eq '8') {return 30;} | ||||
| 0 | |||||||
| 1949 | 0 | 0 | if($number eq '9') {return 31;} | ||||
| 0 | |||||||
| 1950 | } | ||||||
| 1951 | |||||||
| 1952 | sub createFieldXML($$) | ||||||
| 1953 | { | ||||||
| 1954 | 0 | 0 | 0 | my($self, $tag, $value) = @_; | |||
| 1955 | 0 | my $nameattribute; | |||||
| 1956 | 0 | 0 | if($tag =~ /^[1-9]\d*$/) | ||||
| 1957 | { | ||||||
| 1958 | 0 | $nameattribute = "fid"; | |||||
| 1959 | } | ||||||
| 1960 | else | ||||||
| 1961 | { | ||||||
| 1962 | 0 | $nameattribute = "name"; | |||||
| 1963 | } | ||||||
| 1964 | 0 | 0 | if(ref($value) eq "ARRAY") | ||||
| 1965 | { | ||||||
| 1966 | 0 | 0 | if($$value[0] =~ /^file/i) | ||||
| 1967 | { | ||||||
| 1968 | #This is a file attachment! | ||||||
| 1969 | 0 | my $filename = ""; | |||||
| 1970 | 0 | my $buffer = ""; | |||||
| 1971 | 0 | my $filecontents = ""; | |||||
| 1972 | 0 | 0 | if($$value[1] =~ /[\\\/]([^\/\\]+)$/) | ||||
| 1973 | { | ||||||
| 1974 | 0 | $filename = $1; | |||||
| 1975 | } | ||||||
| 1976 | else | ||||||
| 1977 | { | ||||||
| 1978 | 0 | $filename = $$value[1]; | |||||
| 1979 | } | ||||||
| 1980 | 0 | 0 | unless(open(FORUPLOADTOQUICKBASE, "<$$value[1]")) | ||||
| 1981 | { | ||||||
| 1982 | 0 | $filecontents = encode_base64("Sorry QuickBase could not open the file '$$value[1]' for input, for upload to this field in this record.", ""); | |||||
| 1983 | } | ||||||
| 1984 | 0 | binmode FORUPLOADTOQUICKBASE; | |||||
| 1985 | 0 | while (read(FORUPLOADTOQUICKBASE, $buffer, 60*57)) | |||||
| 1986 | { | ||||||
| 1987 | 0 | $filecontents .= encode_base64($buffer, ""); | |||||
| 1988 | } | ||||||
| 1989 | 0 | close FORUPLOADTOQUICKBASE; | |||||
| 1990 | 0 | return " |
|||||
| 1991 | } | ||||||
| 1992 | } | ||||||
| 1993 | else | ||||||
| 1994 | { | ||||||
| 1995 | 0 | $value = $self->xml_escape($value); | |||||
| 1996 | 0 | return " |
|||||
| 1997 | } | ||||||
| 1998 | } | ||||||
| 1999 | |||||||
| 2000 | |||||||
| 2001 | 1; |