function establish(ConnectionConfiguration $connConfig)
 {
     $restConnection = new RestApiClient($this->buildEndpoint($connConfig), $connConfig->getSessionId());
     $restConnection->setCompressionEnabled(WorkbenchConfig::get()->value("enableGzip"));
     $restConnection->setUserAgent(getWorkbenchUserAgent());
     $restConnection->setExternalLogReference($_SESSION['restDebugLog']);
     //TODO: maybe replace w/ its own log?? //TODO: move into ctx
     $restConnection->setLoggingEnabled(WorkbenchConfig::get()->value("debug") == true);
     $restConnection->setProxySettings(getProxySettings());
     $restConnection->setIncludeSessionCookie(WorkbenchConfig::get()->value("includeSessionCookie"));
     return $restConnection;
 }
 public function __construct($sessionId, $clientId, $endpoint, $wsdlPath)
 {
     $_SERVER['HTTP_USER_AGENT'] = getWorkbenchUserAgent();
     $soapClientArray = array();
     if (WorkbenchConfig::get()->value("debug") == true) {
         $soapClientArray['trace'] = 1;
     }
     $soapClientArray['encoding'] = 'utf-8';
     $soapClientArray['exceptions'] = true;
     $soapClientArray['cache_wsdl'] = WSDL_CACHE_NONE;
     //set compression settings
     if (WorkbenchConfig::get()->value("enableGzip") && phpversion() > '5.1.2') {
         $soapClientArray['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | 1;
     }
     //set proxy settings
     if (WorkbenchConfig::get()->value("proxyEnabled") == true) {
         $proxySettings = array();
         $proxySettings['proxy_host'] = WorkbenchConfig::get()->value("proxyHost");
         $proxySettings['proxy_port'] = (int) WorkbenchConfig::get()->value("proxyPort");
         // Use an integer, not a string
         $proxySettings['proxy_login'] = WorkbenchConfig::get()->value("proxyUsername");
         $proxySettings['proxy_password'] = WorkbenchConfig::get()->value("proxyPassword");
         $soapClientArray = array_merge($soapClientArray, $proxySettings);
     }
     $this->sforce = new SoapClient($wsdlPath, $soapClientArray);
     // set session cookie, if enabled
     if (WorkbenchConfig::get()->value("includeSessionCookie")) {
         $this->sforce->__setCookie("sid", $sessionId);
     }
     //start to set headers
     $headerArray = array();
     //set session header
     $sessionVar = array('sessionId' => new SoapVar($sessionId, XSD_STRING));
     $headerBody = new SoapVar($sessionVar, SOAP_ENC_OBJECT);
     $headerArray[] = new SoapHeader($this->getNamespace(), 'SessionHeader', $headerBody, false);
     //set call options header
     if ($clientId != null) {
         $clientBody = array('client' => new SoapVar(WorkbenchConfig::get()->value("callOptions_client"), XSD_STRING));
         $callOptionsHeader = new SoapHeader($this->getNamespace(), 'CallOptions', $clientBody, false);
         $headerArray[] = $callOptionsHeader;
     }
     //set allowFieldTruncationHeader header
     if (WorkbenchConfig::get()->value("allowFieldTruncationHeader_allowFieldTruncation")) {
         $allowFieldTruncationBody = array('allowFieldTruncation' => new SoapVar(WorkbenchConfig::get()->value("allowFieldTruncationHeader_allowFieldTruncation"), XSD_BOOLEAN));
         $allowFieldTruncationHeader = new SoapHeader($this->getNamespace(), 'AllowFieldTruncationHeader', $allowFieldTruncationBody, false);
         $headerArray[] = $allowFieldTruncationHeader;
     }
     $this->sforce->__setSoapHeaders($headerArray);
     $this->sforce->__setLocation($endpoint);
     return $this->sforce;
 }
 function establish(ConnectionConfiguration $connConfig)
 {
     $connection = new SforcePartnerClient();
     $connection->createConnection($this->buildWsdlPath($connConfig));
     $connection->setEndpoint($this->buildEndpoint($connConfig));
     $connection->setSessionHeader($connConfig->getSessionId());
     $connection->setCallOptions(new CallOptions($connConfig->getClientId(), WorkbenchConfig::get()->value('callOptions_defaultNamespace')));
     if (WorkbenchContext::get()->isApiVersionAtLeast(27.0)) {
         if (!WorkbenchConfig::get()->value('ownerChangeOptions_transferAttachments') || !WorkbenchConfig::get()->value('ownerChangeOptions_transferOpenActivities')) {
             $connection->setOwnerChangeOptionsHeader(new OwnerChangeOptionsHeader(WorkbenchConfig::get()->value('ownerChangeOptions_transferAttachments'), WorkbenchConfig::get()->value('ownerChangeOptions_transferOpenActivities')));
         }
     }
     if (WorkbenchConfig::get()->value('assignmentRuleHeader_assignmentRuleId') || WorkbenchConfig::get()->value('assignmentRuleHeader_useDefaultRule')) {
         $connection->setAssignmentRuleHeader(new AssignmentRuleHeader(WorkbenchConfig::get()->value('assignmentRuleHeader_assignmentRuleId'), WorkbenchConfig::get()->value('assignmentRuleHeader_useDefaultRule')));
     }
     if (WorkbenchConfig::get()->value('mruHeader_updateMru')) {
         $connection->setMruHeader(new MruHeader(WorkbenchConfig::get()->value('mruHeader_updateMru')));
     }
     if (WorkbenchConfig::get()->value('queryOptions_batchSize')) {
         $connection->setQueryOptions(new QueryOptions(WorkbenchConfig::get()->value('queryOptions_batchSize')));
     }
     if (WorkbenchConfig::get()->value('emailHeader_triggerAutoResponseEmail') || WorkbenchConfig::get()->value('emailHeader_triggerOtherEmail') || WorkbenchConfig::get()->value('emailHeader_triggertriggerUserEmail')) {
         $connection->setEmailHeader(new EmailHeader(WorkbenchConfig::get()->value('emailHeader_triggerAutoResponseEmail'), WorkbenchConfig::get()->value('emailHeader_triggerOtherEmail'), WorkbenchConfig::get()->value('emailHeader_triggertriggerUserEmail')));
     }
     if (WorkbenchConfig::get()->value('UserTerritoryDeleteHeader_transferToUserId')) {
         $connection->setUserTerritoryDeleteHeader(new UserTerritoryDeleteHeader(WorkbenchConfig::get()->value('UserTerritoryDeleteHeader_transferToUserId')));
     }
     if (WorkbenchConfig::get()->value('allowFieldTruncationHeader_allowFieldTruncation')) {
         $connection->setAllowFieldTruncationHeader(new AllowFieldTruncationHeader(WorkbenchConfig::get()->value('allowFieldTruncationHeader_allowFieldTruncation')));
     }
     if (WorkbenchConfig::get()->value('allOrNoneHeader_allOrNone')) {
         $connection->setAllOrNoneHeader(new AllOrNoneHeader(WorkbenchConfig::get()->value('allOrNoneHeader_allOrNone')));
     }
     if (WorkbenchConfig::get()->value('disableFeedTrackingHeader_disableFeedTracking')) {
         $connection->setDisableFeedTrackingHeader(new DisableFeedTrackingHeader(WorkbenchConfig::get()->value('disableFeedTrackingHeader_disableFeedTracking')));
     }
     if (WorkbenchConfig::get()->value('localOptions_language')) {
         $connection->setLocaleOptions(new LocaleOptions(WorkbenchConfig::get()->value('localOptions_language')));
     }
     if (WorkbenchConfig::get()->value('packageVersionHeader_include') && WorkbenchConfig::get()->value('packageVersion_namespace') && WorkbenchConfig::get()->value('packageVersion_majorNumber') && WorkbenchConfig::get()->value('packageVersion_minorNumber')) {
         $connection->setPackageVersionHeader(WorkbenchConfig::get()->value("packageVersion_namespace"), WorkbenchConfig::get()->value("packageVersion_majorNumber"), WorkbenchConfig::get()->value("packageVersion_minorNumber"));
     }
     return $connection;
 }
 function load($types)
 {
     $describeCache =& $this->getCacheLocation();
     $typesToLoad = array();
     foreach ($types as $type) {
         if (!array_key_exists($type, $describeCache)) {
             $typesToLoad[] = $type;
         }
     }
     if (count($typesToLoad) > 100) {
         throw new Exception("Too many object types to load: " . count($typesToLoad));
     }
     $rawLoadedTypes = WorkbenchContext::get()->getPartnerConnection()->describeSObjects($typesToLoad);
     $loadedTypes = array();
     if ($rawLoadedTypes instanceof stdClass) {
         $loadedTypes = array($rawLoadedTypes->name => $rawLoadedTypes);
     } else {
         if (is_array($rawLoadedTypes)) {
             foreach ($rawLoadedTypes as $rawLoadedType) {
                 $loadedTypes[$rawLoadedType->name] = $rawLoadedType;
             }
         } else {
             throw new Exception("Unknown Describe SObject results");
         }
     }
     foreach ($loadedTypes as $name => $result) {
         if (!is_array($result->fields)) {
             $loadedTypes[$name]->fields = array($result->fields);
         }
         if (WorkbenchConfig::get()->value("abcOrder")) {
             $loadedTypes[$name] = $this->alphaOrderFields($result);
         }
     }
     $requestedTypes =& $loadedTypes;
     foreach ($types as $type) {
         if (array_key_exists($type, $describeCache)) {
             $requestedTypes[$type] = $describeCache[$type];
         }
     }
     return $requestedTypes;
 }
function futureAjax($asyncId)
{
    ?>

<div id="async-container-<?php 
    echo $asyncId;
    ?>
"></div>

<script type='text/javascript' src='<?php 
    echo getPathToStaticResource('/script/getElementsByClassName.js');
    ?>
'></script>

<script type="text/javascript">
    <!--

    var WorkbenchFuture<?php 
    echo $asyncId;
    ?>
 = new function() {
        // Get the HTTP Object
        this.getHTTPObject = function() {
            if (window.ActiveXObject) {
                return new ActiveXObject("Microsoft.XMLHTTP");
            } else if (window.XMLHttpRequest) {
                return new XMLHttpRequest();
            } else {
                alert("Your browser does not support AJAX.");
                return null;
            }
        };

        this.getFuture = function() {
            this.disableWhileAsyncLoading(true);
            var container = document.getElementById('async-container-<?php 
    echo $asyncId;
    ?>
');
            container.innerHTML = "<img src='<?php 
    echo getPathToStaticResource('/images/wait16trans.gif');
    ?>
'/>&nbsp; Loading...";
            this.getFutureInternal(container, 0);
        };

        this.getFutureInternal = function(container, totalTimeWaiting) {
            var ajax = this.getHTTPObject();
            if (ajax != null) {
                var longPollTimeout = 10;
                ajax.open("GET", "future_get.php?async_id=<?php 
    echo $asyncId;
    ?>
&wait_for=" + longPollTimeout, true);
                ajax.send(null);
                ajax.onreadystatechange = function () {
                    if (ajax.readyState == 4) {
                        if (ajax.status == 200) {
                            container.innerHTML = ajax.responseText;
                            var evalables = getElementsByClassName("evalable", "script", container);
                            for (i in evalables) {
                                eval(evalables[i].innerHTML)
                            }
                        } else if (ajax.status == 202) {
                            // 202 means that long poll ended, but still waiting for result
                            container.innerHTML += ".";
                            if (totalTimeWaiting > (<?php 
    echo WorkbenchConfig::get()->value('asyncTimeoutSeconds');
    ?>
)) {
                                container.innerHTML = "<span style='color:red;'>Timed out waiting for asynchronous job to complete</span>";
                            } else {
                                WorkbenchFuture<?php 
    echo $asyncId;
    ?>
.getFutureInternal(container, totalTimeWaiting + longPollTimeout);
                                return;
                            }
                        } else if (ajax.status == 404) {
                            container.innerHTML = "<span style='color:red;'>Unknown Asynchronous Job</span>";
                        } else if (ajax.status == 503) {
                            container.innerHTML = "<span style='color:red;'>Service was temporarily interrupted or is unavailable. Please try again in a moment.</span>";
                        } else {
                            container.innerHTML = "<span style='color:red;'>Unknown Asynchronous State</span>";
                        }
                        WorkbenchFuture<?php 
    echo $asyncId;
    ?>
.disableWhileAsyncLoading(false);
                    }
                };
            } else {
                container.innerHTML = "Unknown error loading content";
            }
        };

        this.disableWhileAsyncLoading = function(isAllowed) {
            var disableWhileAsyncLoadingElements = getElementsByClassName("disableWhileAsyncLoading");

            for (i in disableWhileAsyncLoadingElements) {
                disableWhileAsyncLoadingElements[i].disabled = isAllowed;
            }
        };
    };

    WorkbenchFuture<?php 
    echo $asyncId;
    ?>
.getFuture();

    //-->
</script>

<?php 
}
}
preg_match("@((https?://)((.*)-api)?(.*))/services@", WorkbenchContext::get()->getPartnerConnection()->getLocation(), $sfdcApiHost);
// [1] => https://na4-api.salesforce.com
// [2] => https://
// [3] => na4-api
// [4] => na4
// [5] => .salesforce.com
if ($sfdcApiHost[3] != null) {
    //special cases
    switch ($sfdcApiHost[4]) {
        case "na0":
            $sfdcApiHost[4] = "ssl";
            break;
        case "ap0":
            $sfdcApiHost[4] = "ap";
            break;
        case "eu0":
            $sfdcApiHost[4] = "emea";
            break;
    }
    $sfdcUiHost = $sfdcApiHost[2] . $sfdcApiHost[4] . $sfdcApiHost[5];
} else {
    $sfdcUiHost = $sfdcApiHost[1];
}
if (WorkbenchConfig::get()->value("useSfdcFrontdoor") == 'ALWAYS' || WorkbenchConfig::get()->value("useSfdcFrontdoor") == 'AUTO' && !WorkbenchContext::get()->isUiSessionLikelySet()) {
    WorkbenchContext::get()->setIsUiSessionLikelySet(true);
    $jumpUrl = "{$sfdcUiHost}/secur/frontdoor.jsp?sid=" . WorkbenchContext::get()->getSessionId() . "&retURL=%2F" . $_GET['startUrl'];
} else {
    $jumpUrl = "{$sfdcUiHost}/" . $_GET['startUrl'];
}
header("Location: " . $jumpUrl);
示例#7
0
                    <?php 
printSelectOptions($c->getSubdomainSelectOptions(), $c->getSubdomain());
?>
                </select>
                &nbsp;
                <select id="api" name="api">
                    <?php 
printSelectOptions($c->getApiVersionSelectOptions(), $c->getApiVersion());
?>
                </select>
            </p>
        </div>

        <div class="loginType_std loginType_oauth loginType_adv">
            <p style="display: <?php 
print WorkbenchConfig::get()->value("displayJumpTo") ? "block" : "none";
?>
">
                <label for="startUrl">Jump to:</label>
                <select id="startUrl" name="startUrl" style="width: 18em;">
                    <?php 
printSelectOptions($c->getStartUrlSelectOptions(), $c->getStartUrl());
?>
                </select>
            </p>

            <?php 
if ($c->getTermsFile()) {
    ?>
            <div style="margin-left: 95px;">
                <input type="checkbox" id="termsAccepted" name="termsAccepted"/>
示例#8
0
<?php

include_once 'shared.php';
?>
</div>

<div id='disclaimer'><br />

<?php 
if (WorkbenchConfig::get()->value("checkSSL") && !usingSslEndToEnd()) {
    print "<div style='font-size: 8pt; color: orange;'>WARNING: Unsecure connection detected</div>";
}
if (WorkbenchContext::isEstablished() && WorkbenchContext::get()->isRequestStartTimeSet() && WorkbenchConfig::get()->value("displayRequestTime")) {
    $requestProcessingTime = WorkbenchContext::get()->getRequestProcessingTime();
    workbenchLog(LOG_INFO, "RequestProcessingMetrics", array("measure.request.service" => $requestProcessingTime . "sec", "source" => basename($_SERVER['SCRIPT_NAME'])));
    printf("Requested in %01.3f sec<BR/>", $requestProcessingTime);
}
print "Jason's Workbench " . ($GLOBALS["WORKBENCH_VERSION"] != "trunk" ? $GLOBALS["WORKBENCH_VERSION"] : "") . "<br/>\n";
?>
</div>

</body>

<script type="text/javascript" src="<?php 
echo getPathToStaticResource('/script/wz_tooltip.js');
?>
"></script>

<?php 
if (isset($_REQUEST["footerScripts"])) {
    foreach ($_REQUEST["footerScripts"] as $script) {
 public function setSessionHeader($id)
 {
     if ($id != NULL) {
         $this->sessionHeader = new SoapHeader($this->namespace, 'SessionHeader', array('sessionId' => $id));
         $this->sessionId = $id;
         if (WorkbenchConfig::get()->value("includeSessionCookie")) {
             $this->sforce->__setCookie("sid", $id);
         }
     } else {
         $this->sessionHeader = NULL;
         $this->sessionId = NULL;
     }
 }
示例#10
0
    </head>
<body>

<?php 
if (WorkbenchConfig::get()->isConfigured("displayLiveMaintenanceMessage")) {
    print "<div style='background-color: orange; width: 100%; padding: 2px; font-size: 8pt; font-weight: bold;'>" . "Workbench is currently undergoing maintenance. The service may be intermittently unavailable during this time.</div><br/>";
}
//check for latest version
function strip_seps($haystack)
{
    foreach (array(' ', '_', '-') as $n) {
        $haystack = str_replace($n, "", $haystack);
    }
    return $haystack;
}
if (WorkbenchConfig::get()->value("checkForLatestVersion") && extension_loaded('curl') && (isset($_GET['autoLogin']) || 'login.php' == basename($_SERVER['PHP_SELF']))) {
    try {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://api.github.com/repos/ryanbrainard/forceworkbench/tags');
        curl_setopt($ch, CURLOPT_TIMEOUT, 2);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $tagsResponse = curl_exec($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        if ($tagsResponse === false || $info['http_code'] != 200) {
            throw new Exception("Could not access GitHub tags");
        }
        $tags = json_decode($tagsResponse);
        $betaTagNames = array();
        $gaTagNames = array();
        foreach ($tags as $tag) {
示例#11
0
print "<select  method='POST' name='switchApiVersionTo' onChange='document.changeApiVersionForm.submit();'>";
foreach ($GLOBALS['API_VERSIONS'] as $v) {
    print "<option value='{$v}'";
    if (WorkbenchContext::get()->getApiVersion() == $v) {
        print " selected=\"selected\"";
    }
    print ">" . $v . "</option>";
}
print "</select>";
?>
</form>
</div>

<?php 
$sessionInfo = array();
$sessionInfo['Connection'] = array('API Version' => WorkbenchContext::get()->getApiVersion(), 'Client Id' => isset($_SESSION['tempClientId']) ? $_SESSION['tempClientId'] : WorkbenchConfig::get()->value('callOptions_client'), 'Endpoint' => WorkbenchContext::get()->getPartnerConnection()->getLocation(), 'Session Id' => WorkbenchContext::get()->getPartnerConnection()->getSessionId());
$errors = array();
try {
    foreach (WorkbenchContext::get()->getUserInfo() as $uiKey => $uiValue) {
        if (stripos($uiKey, 'org') !== 0) {
            $sessionInfo['User'][$uiKey] = $uiValue;
        } else {
            $sessionInfo['Organization'][$uiKey] = $uiValue;
        }
    }
} catch (Exception $e) {
    $errors[] = "Partner API Error: " . $e->getMessage();
}
if (WorkbenchContext::get()->isApiVersionAtLeast(10.0)) {
    try {
        foreach (WorkbenchContext::get()->getMetadataConnection()->describeMetadata(WorkbenchContext::get()->getApiVersion()) as $resultsKey => $resultsValue) {
示例#12
0
<?php

require_once 'session.php';
require_once 'shared.php';
require_once 'header.php';
echo file_get_contents(WorkbenchConfig::get()->value("termsFile"));
require_once 'footer.php';
 function isCachingEnabled()
 {
     return WorkbenchConfig::get()->value('cacheDescribeGlobal');
 }
示例#14
0
function debug($showSuperVars = true, $showSoap = true, $customName = null, $customValue = null)
{
    if (WorkbenchConfig::get()->value("debug") == true) {
        print "<script>\n            function toggleDebugSection(title, sectionId) {\n                var section = document.getElementById(sectionId);\n                if (section.style.display == 'inline') {\n                    section.style.display = 'none';\n                    title.childNodes[0].nodeValue = title.childNodes[0].nodeValue.replace('-','+');\n                } else {\n                    title.childNodes[0].nodeValue = title.childNodes[0].nodeValue.replace('+','-');\n                    section.style.display = 'inline';\n                }\n            }\n            </script>";
        print "<div style='text-align: left;'><h1>Debug Mode</h1>";
        if ($customValue) {
            if ($customName) {
                print "<h2>{$customName}</h2>\n";
            } else {
                print "<h2>CUSTOM</h2>\n";
            }
            var_dump($customValue);
            print "<hr/>";
        }
        if ($showSuperVars) {
            print "<h2 onclick=\"toggleDebugSection(this,'container_globals')\" class=\"debugHeader\">+ SUPERGLOBAL VARIABLES</h2>\n";
            print "<div id='container_globals' class='debugContainer'>";
            print "<strong onclick=\"toggleDebugSection(this,'container_globals_cookie')\" class=\"debugHeader\">+ SERVER SUPERGLOBAL VARIABLE</strong>\n";
            print "<div id='container_globals_cookie' class='debugContainer'>";
            print htmlspecialchars(var_export($_SERVER, true), ENT_QUOTES);
            print "<hr/>";
            print "</div>";
            print "<strong onclick=\"toggleDebugSection(this,'container_globals_cookie')\" class=\"debugHeader\">+ COOKIE SUPERGLOBAL VARIABLE</strong>\n";
            print "<div id='container_globals_cookie' class='debugContainer'>";
            print htmlspecialchars(var_export($_COOKIE, true), ENT_QUOTES);
            print "<hr/>";
            print "</div>";
            print "<strong onclick=\"toggleDebugSection(this,'container_globals_session')\" class=\"debugHeader\">+ SESSION SUPERGLOBAL VARIABLE</strong>\n";
            print "<div id='container_globals_session' class='debugContainer'>";
            print htmlspecialchars(var_export($_SESSION, true), ENT_QUOTES);
            print "<hr/>";
            print "</div>";
            print "<strong onclick=\"toggleDebugSection(this,'container_globals_post')\" class=\"debugHeader\">+ POST SUPERGLOBAL VARIABLE</strong>\n";
            print "<div id='container_globals_post' class='debugContainer'>";
            print htmlspecialchars(var_export($_POST, true), ENT_QUOTES);
            print "<hr/>";
            print "</div>";
            print "<strong onclick=\"toggleDebugSection(this,'container_globals_get')\" class=\"debugHeader\">+ GET SUPERGLOBAL VARIABLE</strong>\n";
            print "<div id='container_globals_get' class='debugContainer'>";
            print htmlspecialchars(var_export($_GET, true), ENT_QUOTES);
            print "<hr/>";
            print "</div>";
            print "<strong onclick=\"toggleDebugSection(this,'container_globals_files')\" class=\"debugHeader\">+ FILES SUPERGLOBAL VARIABLE</strong>\n";
            print "<div id='container_globals_files' class='debugContainer'>";
            print htmlspecialchars(var_export($_FILES, true), ENT_QUOTES);
            print "<hr/>";
            print "</div>";
            print "<strong onclick=\"toggleDebugSection(this,'container_globals_env')\" class=\"debugHeader\">+ ENVIRONMENT SUPERGLOBAL VARIABLE</strong>\n";
            print "<div id='container_globals_env' class='debugContainer'>";
            print htmlspecialchars(var_export($_ENV, true), ENT_QUOTES);
            print "<hr/>";
            print "</div>";
            print "</div>";
        }
        // todo: contextify
        if ($showSoap && WorkbenchContext::isEstablished() && WorkbenchContext::get()->getPartnerConnection()->getLastRequestHeaders()) {
            try {
                print "<h2 onclick=\"toggleDebugSection(this,'partner_soap_container')\" class=\"debugHeader\">+ PARTNER SOAP MESSAGES</h2>\n";
                print "<div id='partner_soap_container'  class='debugContainer'>";
                print "<strong>LAST REQUEST HEADER</strong>\n";
                print htmlspecialchars(WorkbenchContext::get()->getPartnerConnection()->getLastRequestHeaders(), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST REQUEST</strong>\n";
                print htmlspecialchars(prettyPrintXml(WorkbenchContext::get()->getPartnerConnection()->getLastRequest()), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST RESPONSE HEADER</strong>\n";
                print htmlspecialchars(WorkbenchContext::get()->getPartnerConnection()->getLastResponseHeaders(), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST RESPONSE</strong>\n";
                print htmlspecialchars(prettyPrintXml(WorkbenchContext::get()->getPartnerConnection()->getLastResponse()), ENT_QUOTES);
                print "<hr/>";
                print "</div>";
            } catch (Exception $e) {
                print "<strong>SOAP Error</strong>\n";
                print_r($e);
            }
        }
        if ($showSoap && WorkbenchContext::isEstablished() && WorkbenchContext::get()->getMetadataConnection()->getLastRequestHeaders()) {
            try {
                print "<h2 onclick=\"toggleDebugSection(this,'metadata_soap_container')\" class=\"debugHeader\">+ METADATA SOAP MESSAGES</h2>\n";
                print "<div id='metadata_soap_container' class='debugContainer'>";
                print "<strong>LAST REQUEST HEADER</strong>\n";
                print htmlspecialchars(WorkbenchContext::get()->getMetadataConnection()->getLastRequestHeaders(), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST REQUEST</strong>\n";
                print htmlspecialchars(prettyPrintXml(WorkbenchContext::get()->getMetadataConnection()->getLastRequest()), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST RESPONSE HEADER</strong>\n";
                print htmlspecialchars(WorkbenchContext::get()->getMetadataConnection()->getLastResponseHeaders(), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST RESPONSE</strong>\n";
                print htmlspecialchars(prettyPrintXml(WorkbenchContext::get()->getMetadataConnection()->getLastResponse()), ENT_QUOTES);
                print "<hr/>";
                print "</div>";
            } catch (Exception $e) {
                print "<strong>SOAP Error</strong>\n";
                print_r($e);
            }
        }
        if ($showSoap && WorkbenchContext::isEstablished() && WorkbenchContext::get()->getApexConnection()->getLastRequestHeaders()) {
            try {
                print "<h2 onclick=\"toggleDebugSection(this,'apex_soap_container')\" class=\"debugHeader\">+ APEX SOAP MESSAGES</h2>\n";
                print "<div id='apex_soap_container' class='debugContainer'>";
                print "<strong>LAST REQUEST HEADER</strong>\n";
                print htmlspecialchars(WorkbenchContext::get()->getApexConnection()->getLastRequestHeaders(), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST REQUEST</strong>\n";
                print htmlspecialchars(prettyPrintXml(WorkbenchContext::get()->getApexConnection()->getLastRequest()), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST RESPONSE HEADER</strong>\n";
                print htmlspecialchars(WorkbenchContext::get()->getApexConnection()->getLastResponseHeaders(), ENT_QUOTES);
                print "<hr/>";
                print "<strong>LAST RESPONSE</strong>\n";
                print htmlspecialchars(prettyPrintXml(WorkbenchContext::get()->getApexConnection()->getLastResponse()), ENT_QUOTES);
                print "<hr/>";
                print "</div>";
            } catch (Exception $e) {
                print "<strong>SOAP Error</strong>\n";
                htmlspecialchars(print_r($e));
            }
        }
        // TODO: move into WbCtx
        if (isset($_SESSION['restDebugLog']) && $_SESSION['restDebugLog'] != "") {
            print "<h2 onclick=\"toggleDebugSection(this,'rest_debug_container')\" class=\"debugHeader\">+ REST/BULK API LOGS</h2>\n";
            print "<div id='rest_debug_container' class='debugContainer'>";
            print "<pre>" . $_SESSION['restDebugLog'] . "</pre>";
            print "<hr/>";
            print "</div>";
            $_SESSION['restDebugLog'] = null;
        }
        print "</div>";
    }
}
 function isCachingEnabled()
 {
     return WorkbenchConfig::get()->value('cacheGetUserInfo');
 }
示例#16
0
function queryAsync($queryRequest)
{
    if ($queryRequest->getQueryAction() == "QueryAll") {
        throw new WorkbenchHandledException("Including deleted and archived records not supported by Bulk Queries.");
    }
    $asyncConnection = WorkbenchContext::get()->getAsyncBulkConnection();
    $job = new JobInfo();
    // try to find actual object in FROM clause in case it is different from object set in form
    preg_match("/FROM\\s(\\w+)/i", $queryRequest->getSoqlQuery(), $fromMatches);
    // if we can't find it, go ahead and use the object from the form.
    // it's probably a malformed query anyway, but let SFDC error on it instead of Workbench
    $job->setObject(isset($fromMatches[1]) ? $fromMatches[1] : $queryRequest->getObject());
    $job->setOpertion("query");
    $job->setContentType(substr($queryRequest->getExportTo(), strlen("async_")));
    $job->setConcurrencyMode(WorkbenchConfig::get()->value("asyncConcurrencyMode"));
    try {
        $job = $asyncConnection->createJob($job);
    } catch (Exception $e) {
        if (strpos($e->getMessage(), 'Unable to find object') > -1 || strpos($e->getMessage(), 'InvalidEntity') > -1) {
            throw new WorkbenchHandledException($e->getMessage());
        } else {
            throw $e;
        }
    }
    $asyncConnection->createBatch($job, $queryRequest->getSoqlQuery());
    $job = $asyncConnection->updateJobState($job->getId(), "Closed");
    header("Location: asyncStatus.php?jobId=" . $job->getId());
}
示例#17
0
<?php

require_once 'session.php';
require_once 'shared.php';
if ($_SESSION) {
    $redirectTime = 2000;
    if (isset($_REQUEST['invalidateSession']) || WorkbenchContext::isEstablished() && WorkbenchConfig::get()->value("invalidateSessionOnLogout")) {
        try {
            if (WorkbenchContext::isEstablished()) {
                WorkbenchContext::get()->getPartnerConnection()->logout();
            }
            $apiSessionInvalidated = true;
        } catch (Exception $e) {
            $apiSessionInvalidated = false;
        }
        if (isset($_SESSION['oauth']['serverUrlPrefix']) && !empty($_SESSION['oauth']['serverUrlPrefix'])) {
            $redirectTime = 5000;
            $uiLogoutIFrame = "<iframe src='" . $_SESSION['oauth']['serverUrlPrefix'] . "/secur/logout.jsp' width='0' height='0' style='display:none;'></iframe>\n";
        }
    } else {
        $apiSessionInvalidated = false;
    }
    session_unset();
    session_destroy();
    require_once 'header.php';
    print "<p/>";
    if (isset($uiLogoutIFrame)) {
        print $uiLogoutIFrame;
    }
    if (isset($_REQUEST['message'])) {
        $redirectTime = 5000;
        continue;
    }
    require_once "async/{$f}";
}
// block direct web access
if (php_sapi_name() != 'cli') {
    httpError(404, "Not Found");
}
$_SERVER['REMOTE_ADDR'] = 'CLI-' . getmypid();
$_SERVER['REQUEST_METHOD'] = 'ASYNC';
// future result gc
$frKeys = redis()->keys(FutureResult::RESULT . "*");
foreach ($frKeys as $frKey) {
    $asyncId = substr($frKey, strlen(FutureResult::RESULT));
    if (!redis()->exists(FUTURE_LOCK . $asyncId)) {
        redis()->del($frKey);
        workbenchLog(LOG_INFO, "FutureResultGC", array("async_id" => $asyncId, "request_id" => $task->requestId, "measure.async.gc.result" => 1 . "result"));
    }
}
workbenchLog(LOG_INFO, "FutureTaskQueueDepth", array("measure.async.queue_depth" => redis()->llen(FutureTask::QUEUE) . "task"));
while (true) {
    try {
        $job = FutureTask::dequeue(30);
        set_time_limit(WorkbenchConfig::get()->value('asyncTimeoutSeconds'));
        $job->execute();
    } catch (TimeoutException $e) {
        continue;
    }
    redis()->close();
    exit;
}
示例#19
0
    httpError("403.4 SSL Required", "Secure connection to Workbench and Salesforce required");
    //TODO: what do we want to do here?
}
//kick user back to login page for any page that requires a session and one isn't established
$myPage = getMyPage();
if (!isLoggedIn() && $myPage->requiresSfdcSession) {
    session_unset();
    session_destroy();
    header('Location: login.php');
    exit;
}
if (!$myPage->isReadOnly && isReadOnlyMode()) {
    throw new WorkbenchHandledException("This page is not accessible in read-only mode");
}
if (WorkbenchContext::isEstablished() && !$myPage->isReadOnly && $_SERVER['REQUEST_METHOD'] == 'POST') {
    validateCsrfToken();
}
if (WorkbenchContext::isEstablished() && isset($_POST['termsAccepted'])) {
    WorkbenchContext::get()->agreeToTerms();
}
if (isLoggedIn()) {
    // todo: should this be in the ctx?
    if (!in_array(basename($_SERVER['PHP_SELF'], ".php"), array("login", "logout")) && isset($_SESSION['lastRequestTime'])) {
        $idleTime = microtime(true) - $_SESSION['lastRequestTime'];
        if ($idleTime > WorkbenchConfig::get()->value("sessionIdleMinutes") * 60) {
            // ping SFDC to check if session is still alive
            WorkbenchContext::get()->getPartnerConnection()->getServerTimestamp();
        }
    }
    $_SESSION['lastRequestTime'] = microtime(true);
}
 function getClientId()
 {
     return isset($this->overriddenClientId) ? $this->overriddenClientId : WorkbenchConfig::get()->value("callOptions_client");
 }
 function getStreamingConfig()
 {
     $streamingConfig["handshakeOnLoad"] = true;
     // TODO: make this configurable
     $streamingConfig["csrfToken"] = getCsrfToken();
     // configs in "$streamingConfig["cometdConfig"]" are loaded into CometD in JS and need to match their format
     $streamingConfig["cometdConfig"]["logLevel"] = "info";
     $streamingConfig["cometdConfig"]["appendMessageTypeToURL"] = false;
     $streamingConfig["cometdConfig"]["advice"]["timeout"] = (int) WorkbenchConfig::get()->valueOrElse("streamingAdviceTimeout", 25000);
     $streamingConfig["cometdConfig"]["advice"]["interval"] = 0;
     $streamingConfig["cometdConfig"]["advice"]["reconnect"] = "retry";
     $streamingConfig["cometdConfig"]["url"] = "http" . (usingSslFromUserToWorkbench() ? "s" : "") . "://" . $_SERVER['HTTP_HOST'] . str_replace('\\', '/', dirname(htmlspecialchars($_SERVER['PHP_SELF']))) . (strlen(dirname(htmlspecialchars($_SERVER['PHP_SELF']))) == 1 ? "" : "/") . "cometdProxy.php";
     return json_encode($streamingConfig);
 }
示例#22
0
    $unsupportedConfigs = array();
    foreach (WorkbenchConfig::get()->entries() as $configKey => $configValue) {
        if (isset($configValue['minApiVersion']) && !WorkbenchContext::get()->isApiVersionAtLeast($configValue['minApiVersion'])) {
            $unsupportedConfigs[] = $configValue['label'] . sprintf(" (Requires %01.1f)", $configValue['minApiVersion']);
        }
    }
    if (count($unsupportedConfigs) > 0) {
        print "<p/>";
        displayWarning(array_merge(array("The following settings will be ignored for your current API version " . WorkbenchContext::get()->getApiVersion() . ":"), $unsupportedConfigs));
        print "<p/><em style='color: orange;'>Quick Fix: <a style='color: orange;' href='sessionInfo.php' target='_blank'>Change API Version</a></em>";
    }
}
print "<p/><form id='settings_form' method='post' action=''>\n";
print "<table border='0' cellspacing='5' style='border-width-top: 1'>\n";
print "<tr> <td colspan='3' align='left'><input type='submit' name='submitConfigSetter' value='Apply Settings'/>&nbsp;<input type='submit' name='restoreDefaults' value='Restore Defaults'/>&nbsp;<input type='reset' value='Cancel'/></td> </tr>";
foreach (WorkbenchConfig::get()->entries() as $configKey => $configValue) {
    // don't even try to deal with complex types
    if (isset($configValue['dataType']) && $configValue['dataType'] == "complex") {
        continue;
    }
    if (isset($configValue['isHeader']) && $configValue['display']) {
        print "\t<tr><th align='left' colspan='3'><br/>" . htmlspecialchars($configValue['label'], ENT_QUOTES) . "</th></tr>\n";
    } else {
        if (isset($configValue['overrideable']) && $configValue['overrideable'] == true) {
            $tip = htmlspecialchars(addslashes($configValue['description']), ENT_NOQUOTES);
            $tip .= isset($configValue['minApiVersion']) ? "<br/><br/>Minimum API Version: " . sprintf("%01.1f", $configValue['minApiVersion']) : "";
            print "\t<tr onmouseover=\"Tip('{$tip}')\">\n";
            print "\t\t<td align='right'><label for='{$configKey}'" . (isLoggedIn() && isset($configValue['minApiVersion']) && !WorkbenchContext::get()->isApiVersionAtLeast($configValue['minApiVersion']) ? " style='color:orange;'" : "") . ">" . htmlspecialchars($configValue['label'], ENT_QUOTES) . "</label></td><td>&nbsp;&nbsp;</td>\n";
            print "\t\t<td align='left'>";
            if ($configValue['dataType'] == "boolean") {
                print "<input name='{$configKey}' id='{$configKey}' type='checkbox' ";
示例#23
0
 /**
  * Executes the task within the user's config and context.
  * The result or any thrown exception is redeemed to a FutureResult with the same async id.
  * Only to be called by CLI. Will error if called from a web process.
  */
 function execute()
 {
     verifyCallingFromCLI();
     $execStartTime = time();
     $future = new FutureResult($this->asyncId);
     try {
         WorkbenchConfig::destroy();
         // destroy the WorkbenchConfig, if one happens to exist
         $_SERVER['HTTP_X_REQUEST_ID'] = $this->requestId;
         // reestablish the original requestId for logging
         $_COOKIE = $this->cookies;
         // reestablish the user's cookies so they'll be picked up by new WorkbenchConfig, if required
         WorkbenchContext::establish($this->connConfig);
         WorkbenchContext::get()->agreeToTerms();
         workbenchLog(LOG_INFO, "FutureTaskExecuteStart", array("async_id" => $this->asyncId, "source" => get_class($this), "measure.async.queue_time" => $execStartTime - $this->enqueueTime . "sec"));
         $future->redeem($this->perform());
     } catch (Exception $e) {
         $future->redeem($e);
     }
     workbenchLog(LOG_INFO, "FutureTaskExecuteEnd", array("async_id" => $this->asyncId, "source" => get_class($this), "measure.async.exec_time" => time() - $execStartTime . "sec"));
     WorkbenchContext::get()->release();
     WorkbenchConfig::destroy();
     $_COOKIE = array();
 }
示例#24
0
function srjb($searchRequest)
{
    return basename($_SERVER['SCRIPT_NAME']) . '?srjb=' . urlencode(base64_encode($searchRequest->toJson())) . (WorkbenchConfig::get()->value("autoJumpToResults") ? '#sr' : '');
}
示例#25
0
 public function getJsConfig()
 {
     $jsConfig = array();
     $jsConfig['useHTTPS'] = (bool) WorkbenchConfig::get()->value('useHTTPS');
     $jsConfig['customServerUrl'] = isset($_REQUEST['serverUrl']) ? $_REQUEST['serverUrl'] : "";
     $jsConfig['serverIdMap'] = $this->getServerIdMap();
     return json_encode($jsConfig);
 }
示例#26
0
 /**
  * Executes the task within the user's config and context.
  * The result or any thrown exception is redeemed to a FutureResult with the same async id.
  * Only to be called by CLI. Will error if called from a web process.
  */
 function execute()
 {
     verifyCallingFromCLI();
     $execStartTime = time();
     $future = new FutureResult($this->asyncId);
     try {
         WorkbenchConfig::destroy();
         // destroy the WorkbenchConfig, if one happens to exist
         $_COOKIE = $this->cookies;
         // reestablish the user's cookies so they'll be picked up by new WorkbenchConfig, if required
         WorkbenchContext::establish($this->connConfig);
         WorkbenchContext::get()->agreeToTerms();
         workbenchLog(LOG_INFO, "FutureTaskExecuteStart", get_class($this) . "-" . $this->asyncId);
         $future->redeem($this->perform());
     } catch (Exception $e) {
         $future->redeem($e);
     }
     workbenchLog(LOG_INFO, "FutureTaskExecuteEnd", get_class($this) . "-" . $this->asyncId . " queueTime=" . ($execStartTime - $this->enqueueTime) . " execTime=" . (time() - $execStartTime));
     WorkbenchContext::get()->release();
     WorkbenchConfig::destroy();
     $_COOKIE = array();
 }
    <?php 
    } else {
        require_once 'header.php';
        ?>
<p class='instructions'>Choose a ZIP file to deploy and any applicable
options:</p>

<form id='deployForm' name='deployForm' method='POST'
    action=''
    enctype='multipart/form-data'><input type='file' name='deployFile'
    size='44' />
    <?php 
        print getCsrfFormTag();
        ?>
    <input type='hidden' name='MAX_FILE_SIZE' value='<?php 
        print WorkbenchConfig::get()->value("maxFileSize");
        ?>
' />
    <img onmouseover="Tip('Choose a ZIP file containing a project manifest, a file named package.xml, and a set of directories that contain the components to deploy.  See Salesforce.com Metadata API Developers guide more information about working with ZIP files for deployment.')"
     align='absmiddle' src='<?php 
        echo getPathToStaticResource('/images/help16.png');
        ?>
' />
<p />
    <?php 
        printDeployOptions(defaultDeployOptions());
        ?>
<p />
<input type='submit' name='stageForDeployment' value='Next' /></form>
    <?php 
    }
示例#28
0
            name="LogCategory">
            <?php 
printSelectOptions(WorkbenchConfig::get()->valuesToLabels('defaultLogCategory'), $_SESSION['LogCategory']);
?>
        </select> &nbsp; Log Level: <select id="LogCategoryLevel"
            name="LogCategoryLevel">
            <?php 
printSelectOptions(WorkbenchConfig::get()->valuesToLabels('defaultLogCategoryLevel'), $_SESSION['LogCategoryLevel']);
?>
        </select></td>
    </tr>
    <tr>
        <td colspan="2"><textarea id='scriptInput' name='scriptInput'
            cols='100'
            rows='<?php 
print WorkbenchConfig::get()->value("textareaRows");
?>
'
            style='overflow: auto; font-family: monospace, courier;'><?php 
echo htmlspecialchars(isset($_SESSION['scriptInput']) ? $_SESSION['scriptInput'] : null, ENT_QUOTES);
?>
</textarea>
        <p />
        <input type='submit' name="execute" value='Execute' class='disableWhileAsyncLoading' /> <input
            type='reset' value='Reset' class='disableWhileAsyncLoading' /></td>
    </tr>
</table>
</form>


<script type="text/javascript">
示例#29
0
function displayBulkApiOptions($action, $forceDoAsync, $recommendDoAsync = false)
{
    //Hard Delete option
    if (WorkbenchContext::get()->isApiVersionAtLeast(19.0) && $action == 'Confirm Delete') {
        print "<p><label><input type='checkbox' id='doHardDelete' name='doHardDelete' onClick=\"" . "if (this.checked && " . ($forceDoAsync ? "false" : "true") . ") {" . "    document.getElementById('doAsync').checked = true;" . "    document.getElementById('asyncDeleteObjectSelection').style.display = 'inline';" . "    document.getElementById('unsupportedBulkConfigList').style.display = 'inline';" . "}\"/> " . "Permanently hard delete records</label>" . "&nbsp;<img onmouseover=\"Tip('When specified, the deleted records are not stored in the Recycle Bin. " . "Instead, the records become immediately eligible for deletion, don\\'t count toward the storage space used " . "by your organization, and may improve performance. The Administrative permission for this operation, " . "\\'Bulk API Hard Delete\\', is disabled by default and must be enabled by an administrator. " . "A Salesforce user license is required for hard delete. Hard Delete is only available via Bulk API.')\" " . "align='absmiddle' src='" . getPathToStaticResource('/images/help16.png') . "'/>" . "</p>";
    }
    //Async Options
    if (WorkbenchContext::get()->isApiVersionAtLeast(17.0) && in_array($action, array('Confirm Insert', 'Confirm Update', 'Confirm Upsert')) || WorkbenchContext::get()->isApiVersionAtLeast(18.0) && $action == 'Confirm Delete') {
        if ($forceDoAsync) {
            print "<input name='doAsync' type='hidden' value='true'/>";
        } else {
            print "<p><label><input id='doAsync' name='doAsync' type='checkbox' " . ($recommendDoAsync ? "checked='checked' " : "") . "onClick=\"" . "var doHardDelete = document.getElementById('doHardDelete');" . "var asyncDeleteObjectSelection = document.getElementById('asyncDeleteObjectSelection');" . "var unsupportedBulkConfigList = document.getElementById('unsupportedBulkConfigList');" . "if (this.checked) {" . "     if (asyncDeleteObjectSelection != null) asyncDeleteObjectSelection.style.display = 'inline';" . "     if (unsupportedBulkConfigList != null) unsupportedBulkConfigList.style.display = 'inline';" . "} else {" . "     if (doHardDelete != null) doHardDelete.checked = false;" . "     if (asyncDeleteObjectSelection != null) asyncDeleteObjectSelection.style.display = 'none';" . "     if (unsupportedBulkConfigList != null) unsupportedBulkConfigList.style.display = 'none';" . "}\"/> " . "Process records asynchronously via Bulk API</label>" . "&nbsp;<img onmouseover=\"Tip('Processing records asynchronously is recommended for large data loads. " . "The data will be uploaded to Salesforce via the Bulk API in batches and processed when server resources are available. " . "After batches have completed, results can be downloaded. Batch size and concurrency options are available in Settings.')\" " . "align='absmiddle' src='" . getPathToStaticResource('/images/help16.png') . "'/>" . "</p>";
        }
        // object selection for Bulk API Delete
        if ($action == 'Confirm Delete') {
            print "<div id='asyncDeleteObjectSelection' style='display: " . ($forceDoAsync || $recommendDoAsync ? "inline" : "none; margin-left: 3em;") . "'>Object Type: ";
            printObjectSelection(WorkbenchContext::get()->getDefaultObject());
            print "</div>";
        }
        // all configs not supported by Bulk API
        $bulkUnsupportedConfigs = array("mruHeader_updateMru", "allOrNoneHeader_allOrNone", "emailHeader_triggerAutoResponseEmail", "emailHeader_triggertriggerUserEmail", "emailHeader_triggerOtherEmail", "allowFieldTruncationHeader_allowFieldTruncation", "UserTerritoryDeleteHeader_transferToUserId");
        // find this user's settings that are in the unsupported config list
        $bulkUnsupportedSettings = array();
        foreach ($bulkUnsupportedConfigs as $c) {
            if (WorkbenchConfig::get()->overridden($c)) {
                $bulkUnsupportedSettings[] = $c;
            }
        }
        // print out a warning if any settings were found
        if (count($bulkUnsupportedSettings) > 0) {
            print "<div id='unsupportedBulkConfigList' style='display: " . ($forceDoAsync || $recommendDoAsync ? "inline" : "none") . "; color: orange;'>" . "<p " . ($forceDoAsync ? "" : "style='margin-left: 3em;'") . ">" . "<img src='" . getPathToStaticResource('/images/warning24.png') . "' /> " . "The following settings are not supported by the Bulk API and will be ignored:" . "<ul " . ($forceDoAsync ? "" : "style='margin-left: 5em;'") . ">";
            foreach ($bulkUnsupportedSettings as $s) {
                print "<li>" . WorkbenchConfig::get()->label($s) . "</li>";
            }
            print "</ul>" . "</p>" . "</div>";
        }
    }
}
 function exportQueryAsCsv($records, $queryAction)
 {
     if (!WorkbenchConfig::get()->value("allowQueryCsvExport")) {
         throw new Exception("Export to CSV not allowed");
     }
     if ($records) {
         try {
             $csvFile = fopen('php://output', 'w') or die("Error opening php://output");
             $csvFilename = "export" . date('YmdHis') . ".csv";
             header("Content-Type: application/csv");
             header("Content-Disposition: attachment; filename={$csvFilename}");
             //Write first row to CSV and unset variable
             fputcsv($csvFile, $this->getQueryResultHeaders(new SObject($records[0])));
             //Export remaining rows and write to CSV line-by-line
             foreach ($records as $record) {
                 fputcsv($csvFile, $this->getQueryResultRow(new SObject($record), false));
             }
             fclose($csvFile) or die("Error closing php://output");
         } catch (Exception $e) {
             require_once "header.php";
             displayQueryForm(new QueryRequest($_POST), 'csv', $queryAction);
             print "<p />";
             displayError($e->getMessage(), false, true);
         }
     } else {
         require_once "header.php";
         displayQueryForm(new QueryRequest($_POST), 'csv', $queryAction);
         print "<p />";
         displayWarning("No records returned for CSV output.", false, true);
     }
 }