added frameworks entities

This commit is contained in:
Infineon\StieberD 2024-03-25 15:15:48 -07:00
parent 81e4baccb1
commit 600a8e1f61
95 changed files with 59733 additions and 0 deletions

View File

@ -0,0 +1,23 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*AGENT_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": "version.GET",
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,26 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*APIROOT_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "APIROOT.HEAD",
"<7,2>": "APIROOT.GET"
},
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,40 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*CONTACTS_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "contacts.HEAD",
"<7,2>": "contacts.GET",
"<7,3>": "contacts.POST",
"<7,4>": "contacts.ID.HEAD",
"<7,5>": "contacts.ID.GET",
"<7,6>": "contacts.ID.PATCH",
"<7,7>": "contacts.ID.PUT",
"<7,8>": "contacts.ID.DELETE",
"<7,9>": "contacts.ID.first_name.HEAD",
"<7,10>": "contacts.ID.first_name.GET",
"<7,11>": "contacts.ID.first_name.PATCH",
"<7,12>": "contacts.ID.last_name.HEAD",
"<7,13>": "contacts.ID.last_name.GET",
"<7,14>": "contacts.ID.last_name.PATCH",
"<7,15>": "contacts.ID.first_name.PUT",
"<7,16>": "contacts.ID.last_name.PUT"
},
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,197 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*DATABASE_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "CalculateColumn",
"<7,2>": "ClearTableHandle",
"<7,3>": "DeleteDataRow",
"<7,4>": "GetKeyIDLock",
"<7,5>": "GetTableCommuter",
"<7,6>": "GetTableHandle",
"<7,7>": "GetTableNames",
"<7,8>": "GetTableProperties",
"<7,9>": "GetUserLocks",
"<7,10>": "IsKeyIDLocked",
"<7,11>": "IsKeyIDSelfLocked",
"<7,12>": "ReadDataRow",
"<7,13>": "ReleaseKeyIDLock",
"<7,14>": "SearchIndex",
"<7,15>": "SetTableAlias",
"<7,16>": "UnlockKeyID",
"<7,17>": "VerifyLH",
"<7,18>": "VerifyLHAll",
"<7,19>": "WriteDataRow"
},
"<8>": {
"<8,1>": "",
"<8,2>": "TableName",
"<8,3>": {
"<8,3,1>": "TableName",
"<8,3,2>": "KeyID",
"<8,3,3>": "IgnoreSelfLock",
"<8,3,4>": "IgnoreMFSRoutines"
},
"<8,4>": {
"<8,4,1>": "TableName",
"<8,4,2>": "KeyID",
"<8,4,3>": "IgnoreSelfLock"
},
"<8,5>": "TableName",
"<8,6>": "TableName",
"<8,7>": {
"<8,7,1>": "ApplicationTablesOnly",
"<8,7,2>": "ExcludeDictionaries",
"<8,7,3>": "ExcludeIndexes"
},
"<8,8>": "TableName",
"<8,9>": "",
"<8,10>": {
"<8,10,1>": "TableName",
"<8,10,2>": "KeyID",
"<8,10,3>": "IgnoreSelfLock"
},
"<8,11>": {
"<8,11,1>": "TableName",
"<8,11,2>": "KeyID"
},
"<8,12>": {
"<8,12,1>": "TableName",
"<8,12,2>": "KeyID",
"<8,12,3>": "NotExpired",
"<8,12,4>": "ExpirationDuration",
"<8,12,5>": "IgnoreMFSRoutines"
},
"<8,13>": {
"<8,13,1>": "TableName",
"<8,13,2>": "KeyID"
},
"<8,14>": {
"<8,14,1>": "TableName",
"<8,14,2>": "ColumnName",
"<8,14,3>": "SearchValue",
"<8,14,4>": "UpdateIndex"
},
"<8,15>": {
"<8,15,1>": "TableName",
"<8,15,2>": "AliasName",
"<8,15,3>": "Volume",
"<8,15,4>": "DatabaseID"
},
"<8,16>": {
"<8,16,1>": "TableName",
"<8,16,2>": "KeyID"
},
"<8,17>": {
"<8,17,1>": "Tablenames",
"<8,17,2>": "SaveList"
},
"<8,18>": "",
"<8,19>": {
"<8,19,1>": "TableName",
"<8,19,2>": "KeyID",
"<8,19,3>": "DataRow",
"<8,19,4>": "IgnoreSelfLock",
"<8,19,5>": "IgnoreMFSRoutines",
"<8,19,6>": "IgnoreAllLocks"
}
},
"<9>": {
"<9,1>": "",
"<9,2>": "",
"<9,3>": {
"<9,3,1>": "",
"<9,3,2>": "",
"<9,3,3>": "",
"<9,3,4>": ""
},
"<9,4>": {
"<9,4,1>": "",
"<9,4,2>": "",
"<9,4,3>": ""
},
"<9,5>": "",
"<9,6>": "",
"<9,7>": {
"<9,7,1>": "BOOLEAN",
"<9,7,2>": "BOOLEAN",
"<9,7,3>": "BOOLEAN"
},
"<9,8>": "",
"<9,9>": "",
"<9,10>": {
"<9,10,1>": "",
"<9,10,2>": "",
"<9,10,3>": "BOOLEAN"
},
"<9,11>": {
"<9,11,1>": "",
"<9,11,2>": ""
},
"<9,12>": {
"<9,12,1>": "",
"<9,12,2>": "",
"<9,12,3>": "",
"<9,12,4>": "",
"<9,12,5>": ""
},
"<9,13>": {
"<9,13,1>": "",
"<9,13,2>": ""
},
"<9,14>": {
"<9,14,1>": "",
"<9,14,2>": "",
"<9,14,3>": "",
"<9,14,4>": ""
},
"<9,15>": {
"<9,15,1>": "",
"<9,15,2>": "",
"<9,15,3>": "",
"<9,15,4>": ""
},
"<9,16>": {
"<9,16,1>": "",
"<9,16,2>": ""
},
"<9,17>": {
"<9,17,1>": "",
"<9,17,2>": ""
},
"<9,18>": "",
"<9,19>": {
"<9,19,1>": "",
"<9,19,2>": "",
"<9,19,3>": "",
"<9,19,4>": "",
"<9,19,5>": "",
"<9,19,6>": ""
}
},
"<10>": "BOOLEAN",
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
}
},
"<12>": "0"
}
}
}

View File

@ -0,0 +1,65 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*ERROR_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "Set",
"<7,2>": "Add",
"<7,3>": "Clear",
"<7,4>": "GetMessage",
"<7,5>": "GetMessages",
"<7,6>": "HasError",
"<7,7>": "NoError",
"<7,8>": "DisplayError",
"<7,9>": "GetSource",
"<7,10>": "GetSources",
"<7,11>": "GetCode",
"<7,12>": "GetCodes",
"<7,13>": "GetStackTrace"
},
"<8>": {
"<8,1>": "ErrorMessage",
"<8,2>": "ErrorMessage",
"<8,3>": "",
"<8,4>": "",
"<8,5>": "",
"<8,6>": "",
"<8,7>": "",
"<8,8>": "Justification"
},
"<9>": {
"<9,1>": "",
"<9,2>": "",
"<9,3>": "",
"<9,4>": "",
"<9,5>": "",
"<9,6>": "",
"<9,7>": "",
"<9,8>": ""
},
"<10>": "BOOLEAN",
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
}
},
"<12>": "0"
}
}
}

View File

@ -0,0 +1,186 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*HTTPCLIENT_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "SendHTTPRequestOLE",
"<7,2>": "SendHTTPRequest",
"<7,3>": "SetRequestHeaderFields",
"<7,4>": "SetRequestHeaderField",
"<7,5>": "GetRequestHeaderFields",
"<7,6>": "GetRequestHeaderField",
"<7,7>": "SetResponseHeaderField",
"<7,8>": "GetResponseHeaderFields",
"<7,9>": "GetResponseHeaderField",
"<7,10>": "GetCookies",
"<7,11>": "GetCookie",
"<7,12>": "SetResponseStatusCode",
"<7,13>": "GetResponseStatusCode",
"<7,14>": "SetResponseStatusPhrase",
"<7,15>": "GetResponseStatusPhrase",
"<7,16>": "SetResponseBody",
"<7,17>": "GetResponseBody",
"<7,18>": "SetTimeoutDuration",
"<7,19>": "GetTimeoutDuration",
"<7,20>": "ClearResponseSettings",
"<7,21>": "ClearRequestSettings"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "Method",
"<8,1,2>": "URL",
"<8,1,3>": "HeaderList",
"<8,1,4>": "Body",
"<8,1,5>": "ProxyUser",
"<8,1,6>": "ProxyPassword",
"<8,1,7>": "UseAsynchronous",
"<8,1,8>": "UseClientXMLHTTP",
"<8,1,9>": "ClientCertPath"
},
"<8,2>": {
"<8,2,1>": "Method",
"<8,2,2>": "URL",
"<8,2,3>": "HeaderList",
"<8,2,4>": "Body",
"<8,2,5>": "ProxyUser",
"<8,2,6>": "ProxyPassword",
"<8,2,7>": "UseAsynchronous",
"<8,2,8>": "UseClientXMLHTTP",
"<8,2,9>": "ClientCertPath"
},
"<8,3>": "HeaderList",
"<8,4>": {
"<8,4,1>": "Name",
"<8,4,2>": "Value"
},
"<8,5>": "",
"<8,6>": "Name",
"<8,7>": {
"<8,7,1>": "Name",
"<8,7,2>": "Value"
},
"<8,8>": "",
"<8,9>": {
"<8,9,1>": "Name",
"<8,9,2>": "Delimiter"
},
"<8,10>": "Delimiter",
"<8,11>": {
"<8,11,1>": "Name",
"<8,11,2>": "IgnoreAttributes"
},
"<8,12>": "Code",
"<8,13>": "",
"<8,14>": "Phrase",
"<8,15>": "",
"<8,16>": "Body",
"<8,17>": "",
"<8,18>": "TimeoutDuration"
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": "",
"<9,1,3>": "",
"<9,1,4>": "",
"<9,1,5>": "",
"<9,1,6>": "",
"<9,1,7>": "",
"<9,1,8>": "",
"<9,1,9>": ""
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": "",
"<9,2,3>": "",
"<9,2,4>": "",
"<9,2,5>": "",
"<9,2,6>": "",
"<9,2,7>": "",
"<9,2,8>": "",
"<9,2,9>": ""
},
"<9,3>": "",
"<9,4>": {
"<9,4,1>": "",
"<9,4,2>": ""
},
"<9,5>": "",
"<9,6>": "",
"<9,7>": {
"<9,7,1>": "",
"<9,7,2>": ""
},
"<9,8>": "",
"<9,9>": {
"<9,9,1>": "RESPONSEHEADERNAMES",
"<9,9,2>": ""
},
"<9,10>": "",
"<9,11>": {
"<9,11,1>": "",
"<9,11,2>": "BOOLEAN"
},
"<9,12>": "",
"<9,13>": "",
"<9,14>": "",
"<9,15>": "",
"<9,16>": "",
"<9,17>": "",
"<9,18>": ""
},
"<10>": {
"<10,1>": "BOOLEAN",
"<10,2>": "RESPONSEHEADERNAMES"
},
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
},
"<11,2>": {
"<11,2,1>": "Access-Control-Allow-Headers",
"<11,2,2>": "Access-Control-Allow-Methods",
"<11,2,3>": "Access-Control-Allow-Origin",
"<11,2,4>": "Allow",
"<11,2,5>": "Content-Encoding",
"<11,2,6>": "Content-Language",
"<11,2,7>": "Content-Length",
"<11,2,8>": "Content-Location",
"<11,2,9>": "Content-Disposition",
"<11,2,10>": "Content-Type",
"<11,2,11>": "Date",
"<11,2,12>": "Expires",
"<11,2,13>": "Last-Modified",
"<11,2,14>": "Link",
"<11,2,15>": "Location",
"<11,2,16>": "Retry-After",
"<11,2,17>": "Server",
"<11,2,18>": "Set-Cookie",
"<11,2,19>": "Transfer-Encoding",
"<11,2,20>": "Vary",
"<11,2,21>": "WWW-Authenticate"
}
},
"<12>": {
"<12,1>": "0",
"<12,2>": "1"
}
}
}
}

View File

@ -0,0 +1,102 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*HTTP_AUTHENTICATION_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "AuthenticateRequest",
"<7,2>": "CleanUp",
"<7,3>": "GetWebAccountEnabledStatus",
"<7,4>": "GetWebAccountPassword",
"<7,5>": "ResetWebAccountPassword",
"<7,6>": "ValidateWebAccountPassword",
"<7,7>": "SetWebAccountPassword",
"<7,8>": "SetAuthenticatedAccountID",
"<7,9>": "GetAuthenticatedAccountID",
"<7,10>": "SetAuthenticatedPassword",
"<7,11>": "GetAuthenticatedPassword",
"<7,12>": "ContainmentActionNotification"
},
"<8>": {
"<8,1>": "",
"<8,2>": "",
"<8,3>": "AccountID",
"<8,4>": {
"<8,4,1>": "AccountID",
"<8,4,2>": "CreateIfNew"
},
"<8,5>": {
"<8,5,1>": "AccountID",
"<8,5,2>": "CurrentPassword"
},
"<8,6>": {
"<8,6,1>": "AccountID",
"<8,6,2>": "Password",
"<8,6,3>": "CurrentOnly"
},
"<8,7>": {
"<8,7,1>": "AccountID",
"<8,7,2>": "CurrentPassword",
"<8,7,3>": "NewPassword",
"<8,7,4>": "OverrideExpireDate"
},
"<8,8>": "AccountID",
"<8,9>": "",
"<8,10>": "Password",
"<8,11>": "",
"<8,12>": "ActionDetails"
},
"<9>": {
"<9,1>": "",
"<9,2>": "",
"<9,3>": "",
"<9,4>": {
"<9,4,1>": "",
"<9,4,2>": ""
},
"<9,5>": {
"<9,5,1>": "",
"<9,5,2>": ""
},
"<9,6>": {
"<9,6,1>": "",
"<9,6,2>": "",
"<9,6,3>": ""
},
"<9,7>": {
"<9,7,1>": "",
"<9,7,2>": "",
"<9,7,3>": "",
"<9,7,4>": ""
},
"<9,8>": "",
"<9,9>": "",
"<9,10>": "",
"<9,11>": "",
"<9,12>": ""
},
"<10>": "BOOLEAN",
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
}
},
"<12>": "0"
}
}
}

View File

@ -0,0 +1,155 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*HTTP_JSON_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "SetHALItem",
"<7,2>": "SetHALCollection",
"<7,3>": "SetHALCollectionEmbedded",
"<7,4>": "SetHALLinks",
"<7,5>": "SetHALEmbedded",
"<7,6>": "GetHALRootObj",
"<7,7>": "GetHAL",
"<7,8>": "GetSchemaRootObj",
"<7,9>": "SetSchemaMeta",
"<7,10>": "SetSchemaProperty",
"<7,11>": "GetSchema",
"<7,12>": "GetURLFromID",
"<7,13>": "GetIDFromURL"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "ItemURL",
"<8,1,2>": "ColumnNames",
"<8,1,3>": "ColumnValues",
"<8,1,4>": "DataTypes",
"<8,1,5>": "MVGroupNames"
},
"<8,2>": {
"<8,2,1>": "CollectionURL",
"<8,2,2>": "ItemsURLs",
"<8,2,3>": "ItemsTitles"
},
"<8,3>": {
"<8,3,1>": "CollectionURL",
"<8,3,2>": "ItemsURLs",
"<8,3,3>": "ColumnNames",
"<8,3,4>": "ColumnValues",
"<8,3,5>": "DataTypes",
"<8,3,6>": "MVGroupNames"
},
"<8,4>": {
"<8,4,1>": "SelfURI",
"<8,4,2>": "HREFNames",
"<8,4,3>": "HREFURIs",
"<8,4,4>": "ChildNames",
"<8,4,5>": "hChildren",
"<8,4,6>": "Names",
"<8,4,7>": "Values"
},
"<8,5>": "",
"<8,6>": "",
"<8,7>": "ItemArrayLabel",
"<8,8>": "",
"<8,9>": {
"<8,9,1>": "Title",
"<8,9,2>": "Description",
"<8,9,3>": "Type"
},
"<8,10>": {
"<8,10,1>": "Name",
"<8,10,2>": "Title",
"<8,10,3>": "Type",
"<8,10,4>": "Format",
"<8,10,5>": "EnumList",
"<8,10,6>": "Required"
},
"<8,11>": "",
"<8,12>": "ID",
"<8,13>": {
"<8,13,1>": "URL",
"<8,13,2>": "Array",
"<8,13,3>": "Table"
}
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": "",
"<9,1,3>": "",
"<9,1,4>": "",
"<9,1,5>": ""
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": "",
"<9,2,3>": ""
},
"<9,3>": {
"<9,3,1>": "",
"<9,3,2>": "",
"<9,3,3>": "",
"<9,3,4>": "",
"<9,3,5>": "",
"<9,3,6>": ""
},
"<9,4>": {
"<9,4,1>": "",
"<9,4,2>": "",
"<9,4,3>": "",
"<9,4,4>": "",
"<9,4,5>": "",
"<9,4,6>": "",
"<9,4,7>": ""
},
"<9,5>": "",
"<9,6>": "",
"<9,7>": "",
"<9,8>": "",
"<9,9>": {
"<9,9,1>": "",
"<9,9,2>": "",
"<9,9,3>": ""
},
"<9,10>": {
"<9,10,1>": "",
"<9,10,2>": "",
"<9,10,3>": "",
"<9,10,4>": "",
"<9,10,5>": "",
"<9,10,6>": ""
},
"<9,11>": "",
"<9,12>": "",
"<9,13>": {
"<9,13,1>": "",
"<9,13,2>": "",
"<9,13,3>": ""
}
},
"<10>": "BOOLEAN",
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
}
},
"<12>": "0"
}
}
}

View File

@ -0,0 +1,140 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*HTTP_RESOURCE_MANAGER_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "GetResourceProperty",
"<7,2>": "SetResourceProperty",
"<7,3>": "GetResourceChildren",
"<7,4>": "GetResourceSignature",
"<7,5>": "GetEndpointResourceKeyID",
"<7,6>": "GetResource",
"<7,7>": "SetResource",
"<7,8>": "IsValidEndpoint",
"<7,9>": "GetResourceList"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "URLEndpoint",
"<8,1,2>": "PropertyName"
},
"<8,2>": {
"<8,2,1>": "URLEndpoint",
"<8,2,2>": "PropertyName",
"<8,2,3>": "PropertyValue"
},
"<8,3>": {
"<8,3,1>": "URLEndpoint",
"<8,3,2>": "ChildType"
},
"<8,4>": {
"<8,4,1>": "URLEndpoint",
"<8,4,2>": "Method"
},
"<8,5>": {
"<8,5,1>": "URLEndpoint",
"<8,5,2>": "AllowNew"
},
"<8,6>": "URLEndpoint",
"<8,7>": {
"<8,7,1>": "URLEndpoint",
"<8,7,2>": "PropertyArray"
},
"<8,8>": "URLEndpoint"
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": "PROPERTIES"
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": "PROPERTIES",
"<9,2,3>": ""
},
"<9,3>": {
"<9,3,1>": "",
"<9,3,2>": "CHILDREN"
},
"<9,4>": {
"<9,4,1>": "",
"<9,4,2>": "METHODS"
},
"<9,5>": {
"<9,5,1>": "",
"<9,5,2>": ""
},
"<9,6>": "",
"<9,7>": {
"<9,7,1>": "",
"<9,7,2>": ""
},
"<9,8>": ""
},
"<10>": {
"<10,1>": "BOOLEAN",
"<10,2>": "CLASSES",
"<10,3>": "PROPERTIES",
"<10,4>": "CHILDREN",
"<10,5>": "METHODS"
},
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
},
"<11,2>": {
"<11,2,1>": "APIROOT",
"<11,2,2>": "RESOURCE",
"<11,2,3>": "RESOURCE_ID",
"<11,2,4>": "PROPERTY"
},
"<11,3>": {
"<11,3,1>": "CLASS",
"<11,3,2>": "DESCRIPTION",
"<11,3,3>": "EXCLUDE_LOGGING",
"<11,3,4>": "METHODS",
"<11,3,5>": "NAME",
"<11,3,6>": "RESOURCE",
"<11,3,7>": "TITLE",
"<11,3,8>": "QUERY_PARAMS"
},
"<11,4>": {
"<11,4,1>": "ALL",
"<11,4,2>": "RESOURCE",
"<11,4,3>": "RESOURCE_ID",
"<11,4,4>": "PROPERTY"
},
"<11,5>": {
"<11,5,1>": "GET",
"<11,5,2>": "POST",
"<11,5,3>": "PUT",
"<11,5,4>": "PATCH",
"<11,5,5>": "DELETE"
}
},
"<12>": {
"<12,1>": "0",
"<12,2>": "1",
"<12,3>": "1",
"<12,4>": "1",
"<12,5>": "1"
}
}
}
}

View File

@ -0,0 +1,444 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*HTTP_RESOURCE_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "GetObject",
"<7,2>": "GetObjects",
"<7,3>": "ParseResource",
"<7,4>": "AddProperty",
"<7,5>": "AddProperties",
"<7,6>": "AddSubProperty",
"<7,7>": "AddSubProperties",
"<7,8>": "AddSubResourceObject",
"<7,9>": "AddSubResourceObjects",
"<7,10>": "AddSubResource",
"<7,11>": "AddSubResources",
"<7,12>": "AddLinkRelation",
"<7,13>": "AddLinkRelations",
"<7,14>": "AddEmbeddedResources",
"<7,15>": "AddFormAction",
"<7,16>": "GetSerializedResource",
"<7,17>": "LoremIpsum",
"<7,18>": "GetURLTemplate",
"<7,19>": "GetDatabaseItem",
"<7,20>": "GetDatabaseItems",
"<7,21>": "DeleteDatabaseItem",
"<7,22>": "PutDatabaseItem",
"<7,23>": "PostDatabaseItem",
"<7,24>": "PatchDatabaseItem",
"<7,25>": "GetColumnNames",
"<7,26>": "GetColumnValues",
"<7,27>": "GetMVGroupNames"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "TableName",
"<8,1,2>": "KeyID",
"<8,1,3>": "ColumnNames",
"<8,1,4>": "PropertyNames",
"<8,1,5>": "DataTypes",
"<8,1,6>": "MVGroupNames",
"<8,1,7>": "NestedGroupNames",
"<8,1,8>": "BaseSelfRelURL",
"<8,1,9>": "KeyParts",
"<8,1,10>": "KeyDelimiter",
"<8,1,11>": "AllowKeyProperty"
},
"<8,2>": {
"<8,2,1>": "TableName",
"<8,2,2>": "Filter",
"<8,2,3>": "ColumnNames",
"<8,2,4>": "PropertyNames",
"<8,2,5>": "DataTypes",
"<8,2,6>": "MVGroupNames",
"<8,2,7>": "NestedGroupNames",
"<8,2,8>": "BaseSelfRelURL",
"<8,2,9>": "KeyParts",
"<8,2,10>": "KeyDelimiter",
"<8,2,11>": "AllowKeyProperty"
},
"<8,3>": "SerializedResource",
"<8,4>": {
"<8,4,1>": "ObjectHandle",
"<8,4,2>": "PropertyName",
"<8,4,3>": "PropertyValue",
"<8,4,4>": "DataType"
},
"<8,5>": {
"<8,5,1>": "ObjectHandle",
"<8,5,2>": "PropertyNames",
"<8,5,3>": "PropertyValues",
"<8,5,4>": "DataTypes"
},
"<8,6>": {
"<8,6,1>": "ObjectHandle",
"<8,6,2>": "PropertyName",
"<8,6,3>": "SubPropertyName",
"<8,6,4>": "SubPropertyValue",
"<8,6,5>": "DataType"
},
"<8,7>": {
"<8,7,1>": "ObjectHandle",
"<8,7,2>": "PropertyName",
"<8,7,3>": "SubPropertyNames",
"<8,7,4>": "SubPropertyValues",
"<8,7,5>": "DataTypes"
},
"<8,8>": {
"<8,8,1>": "ObjectHandle",
"<8,8,2>": "PropertyName",
"<8,8,3>": "SubResourceObjectHandle"
},
"<8,9>": {
"<8,9,1>": "ObjectHandle",
"<8,9,2>": "PropertyName",
"<8,9,3>": "SubResourceObjectHandles"
},
"<8,10>": {
"<8,10,1>": "ObjectHandle",
"<8,10,2>": "PropertyName",
"<8,10,3>": "SubResourcePropertyNames",
"<8,10,4>": "SubResourcePropertyValues",
"<8,10,5>": "DataTypes"
},
"<8,11>": {
"<8,11,1>": "ObjectHandle",
"<8,11,2>": "PropertyName",
"<8,11,3>": "SubResourcePropertyNames",
"<8,11,4>": "SubResourcePropertyValuesArray",
"<8,11,5>": "DataTypes"
},
"<8,12>": {
"<8,12,1>": "ObjectHandle",
"<8,12,2>": "Relation",
"<8,12,3>": "URL",
"<8,12,4>": "Title",
"<8,12,5>": "IsTemplate",
"<8,12,6>": "IgnoreResourceID",
"<8,12,7>": "IgnoreProperty",
"<8,12,8>": "IgnoreQueryParam"
},
"<8,13>": {
"<8,13,1>": "ObjectHandle",
"<8,13,2>": "Relations",
"<8,13,3>": "URLs",
"<8,13,4>": "Titles",
"<8,13,5>": "IsTemplates",
"<8,13,6>": "IgnoreResourceIDs",
"<8,13,7>": "IgnoreProperties",
"<8,13,8>": "IgnoreQueryParams"
},
"<8,14>": {
"<8,14,1>": "ObjectHandle",
"<8,14,2>": "EmbeddedResourceName",
"<8,14,3>": "EmbeddedResourceObjectHandles",
"<8,14,4>": "Singular"
},
"<8,15>": {
"<8,15,1>": "ObjectHandle",
"<8,15,2>": "Name",
"<8,15,3>": "Method",
"<8,15,4>": "URL",
"<8,15,5>": "Title",
"<8,15,6>": "Fields",
"<8,15,7>": "FieldProperties"
},
"<8,16>": {
"<8,16,1>": "ObjectHandle",
"<8,16,2>": "Style"
},
"<8,17>": "",
"<8,18>": {
"<8,18,1>": "URL",
"<8,18,2>": "IgnoreResourceID",
"<8,18,3>": "IgnoreProperty",
"<8,18,4>": "IgnoreQueryParam"
},
"<8,19>": {
"<8,19,1>": "TableName",
"<8,19,2>": "SelfURL",
"<8,19,3>": "KeyID",
"<8,19,4>": "ColumnNames",
"<8,19,5>": "ItemArrayLabel"
},
"<8,20>": {
"<8,20,1>": "Filter",
"<8,20,2>": "TableName",
"<8,20,3>": "SelfURL",
"<8,20,4>": "ColumnNames",
"<8,20,5>": "ItemArrayLabel"
},
"<8,21>": {
"<8,21,1>": "TableName",
"<8,21,2>": "KeyID"
},
"<8,22>": {
"<8,22,1>": "TableName",
"<8,22,2>": "SelfURL",
"<8,22,3>": "KeyID",
"<8,22,4>": "AllowedColumnNames"
},
"<8,23>": {
"<8,23,1>": "TableName",
"<8,23,2>": "SelfURL",
"<8,23,3>": "AllowedColumnNames"
},
"<8,24>": {
"<8,24,1>": "TableName",
"<8,24,2>": "SelfURL",
"<8,24,3>": "KeyID",
"<8,24,4>": "AllowedColumnNames"
},
"<8,25>": {
"<8,25,1>": "TableName",
"<8,25,2>": "ColumnNames",
"<8,25,3>": "AllowKeyProperty"
},
"<8,26>": {
"<8,26,1>": "TableName",
"<8,26,2>": "ColumnNames",
"<8,26,3>": "KeyID"
},
"<8,27>": {
"<8,27,1>": "TableName",
"<8,27,2>": "ColumnNames"
}
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": "",
"<9,1,3>": "",
"<9,1,4>": "",
"<9,1,5>": "",
"<9,1,6>": "",
"<9,1,7>": "",
"<9,1,8>": "",
"<9,1,9>": "",
"<9,1,10>": "",
"<9,1,11>": ""
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": "",
"<9,2,3>": "",
"<9,2,4>": "",
"<9,2,5>": "",
"<9,2,6>": "",
"<9,2,7>": "",
"<9,2,8>": "",
"<9,2,9>": "",
"<9,2,10>": "",
"<9,2,11>": ""
},
"<9,3>": "",
"<9,4>": {
"<9,4,1>": "",
"<9,4,2>": "",
"<9,4,3>": "",
"<9,4,4>": "ALLDATATYPES"
},
"<9,5>": {
"<9,5,1>": "",
"<9,5,2>": "",
"<9,5,3>": "",
"<9,5,4>": ""
},
"<9,6>": {
"<9,6,1>": "",
"<9,6,2>": "",
"<9,6,3>": "",
"<9,6,4>": "",
"<9,6,5>": "ALLDATATYPES"
},
"<9,7>": {
"<9,7,1>": "",
"<9,7,2>": "",
"<9,7,3>": "",
"<9,7,4>": "",
"<9,7,5>": ""
},
"<9,8>": {
"<9,8,1>": "",
"<9,8,2>": "",
"<9,8,3>": ""
},
"<9,9>": {
"<9,9,1>": "",
"<9,9,2>": "",
"<9,9,3>": ""
},
"<9,10>": {
"<9,10,1>": "",
"<9,10,2>": "",
"<9,10,3>": "",
"<9,10,4>": "",
"<9,10,5>": ""
},
"<9,11>": {
"<9,11,1>": "",
"<9,11,2>": "",
"<9,11,3>": "",
"<9,11,4>": "",
"<9,11,5>": ""
},
"<9,12>": {
"<9,12,1>": "",
"<9,12,2>": "",
"<9,12,3>": "",
"<9,12,4>": "",
"<9,12,5>": "BOOLEAN",
"<9,12,6>": "BOOLEAN",
"<9,12,7>": "BOOLEAN",
"<9,12,8>": "BOOLEAN"
},
"<9,13>": {
"<9,13,1>": "",
"<9,13,2>": "",
"<9,13,3>": "",
"<9,13,4>": "",
"<9,13,5>": "",
"<9,13,6>": "BOOLEAN",
"<9,13,7>": "BOOLEAN",
"<9,13,8>": "BOOLEAN"
},
"<9,14>": {
"<9,14,1>": "",
"<9,14,2>": "",
"<9,14,3>": "",
"<9,14,4>": ""
},
"<9,15>": {
"<9,15,1>": "",
"<9,15,2>": "",
"<9,15,3>": "METHODS",
"<9,15,4>": "",
"<9,15,5>": "",
"<9,15,6>": "",
"<9,15,7>": ""
},
"<9,16>": {
"<9,16,1>": "",
"<9,16,2>": "STYLES"
},
"<9,17>": "",
"<9,18>": {
"<9,18,1>": "",
"<9,18,2>": "BOOLEAN",
"<9,18,3>": "BOOLEAN",
"<9,18,4>": "BOOLEAN"
},
"<9,19>": {
"<9,19,1>": "",
"<9,19,2>": "",
"<9,19,3>": "",
"<9,19,4>": "",
"<9,19,5>": ""
},
"<9,20>": {
"<9,20,1>": "",
"<9,20,2>": "",
"<9,20,3>": "",
"<9,20,4>": "",
"<9,20,5>": ""
},
"<9,21>": {
"<9,21,1>": "",
"<9,21,2>": ""
},
"<9,22>": {
"<9,22,1>": "",
"<9,22,2>": "",
"<9,22,3>": "",
"<9,22,4>": ""
},
"<9,23>": {
"<9,23,1>": "",
"<9,23,2>": "",
"<9,23,3>": ""
},
"<9,24>": {
"<9,24,1>": "",
"<9,24,2>": "",
"<9,24,3>": "",
"<9,24,4>": ""
},
"<9,25>": {
"<9,25,1>": "",
"<9,25,2>": "",
"<9,25,3>": ""
},
"<9,26>": {
"<9,26,1>": "",
"<9,26,2>": "",
"<9,26,3>": ""
},
"<9,27>": {
"<9,27,1>": "",
"<9,27,2>": ""
}
},
"<10>": {
"<10,1>": "BOOLEAN",
"<10,2>": "LAYOUT",
"<10,3>": "METHODS",
"<10,4>": "STYLES",
"<10,5>": "ALLDATATYPES"
},
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
},
"<11,2>": {
"<11,2,1>": "Array",
"<11,2,2>": "List"
},
"<11,3>": {
"<11,3,1>": "GET",
"<11,3,2>": "POST",
"<11,3,3>": "PUT",
"<11,3,4>": "PATCH",
"<11,3,5>": "DELETE"
},
"<11,4>": {
"<11,4,1>": "Fast",
"<11,4,2>": "Styled",
"<11,4,3>": "DropNulls"
},
"<11,5>": {
"<11,5,1>": "String",
"<11,5,2>": "Number",
"<11,5,3>": "Boolean",
"<11,5,4>": "StringList",
"<11,5,5>": "NumberList",
"<11,5,6>": "BooleanList",
"<11,5,7>": "ObjectHandle"
}
},
"<12>": {
"<12,1>": "0",
"<12,2>": "1",
"<12,3>": "1",
"<12,4>": "1",
"<12,5>": "1"
}
}
}
}

View File

@ -0,0 +1,592 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*HTTP_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "RunWebAPI",
"<7,2>": "RunHTTPService",
"<7,3>": "SetSelfURL",
"<7,4>": "GetSelfURL",
"<7,5>": "SetSessionID",
"<7,6>": "GetSessionID",
"<7,7>": "CreateLogFile",
"<7,8>": "SetOECGIRequest",
"<7,9>": "GetOECGIRequest",
"<7,10>": "SetOECGIProcErr",
"<7,11>": "GetOECGIProcErr",
"<7,12>": "SetHTTPQueryString",
"<7,13>": "SetHTTPPathInfo",
"<7,14>": "SetHTTPContentType",
"<7,15>": "SetHTTPContentLength",
"<7,16>": "SetHTTPGatewayInterface",
"<7,17>": "SetHTTPHTTPS",
"<7,18>": "SetHTTPAccept",
"<7,19>": "SetHTTPCookie",
"<7,20>": "SetHTTPFrom",
"<7,21>": "SetHTTPReferer",
"<7,22>": "SetHTTPUserAgent",
"<7,23>": "SetHTTPTranslated",
"<7,24>": "SetHTTPRemoteAddr",
"<7,25>": "SetHTTPRemoteHost",
"<7,26>": "SetHTTPRemoteIdent",
"<7,27>": "SetHTTPRemoteUser",
"<7,28>": "SetHTTPRequestMethod",
"<7,29>": "SetHTTPScriptName",
"<7,30>": "SetHTTPServerName",
"<7,31>": "SetHTTPServerPort",
"<7,32>": "SetHTTPServerProtocol",
"<7,33>": "SetHTTPServerSoftware",
"<7,34>": "SetHTTPServerURL",
"<7,35>": "SetHTTPNoURLDecode",
"<7,36>": "SetHTTPResponseIsBinary",
"<7,37>": "SetHTTPRegistrySettings",
"<7,38>": "SetHTTPOECGIVersion",
"<7,39>": "SetHTTPGetString",
"<7,40>": "SetHTTPPostString",
"<7,41>": "SetHTTPAdditionalValues",
"<7,42>": "GetHTTPQueryString",
"<7,43>": "GetHTTPPathInfo",
"<7,44>": "GetHTTPContentType",
"<7,45>": "GetHTTPContentLength",
"<7,46>": "GetHTTPGatewayInterface",
"<7,47>": "GetHTTPHTTPS",
"<7,48>": "GetHTTPAccept",
"<7,49>": "GetHTTPCookie",
"<7,50>": "GetHTTPFrom",
"<7,51>": "GetHTTPReferer",
"<7,52>": "GetHTTPUserAgent",
"<7,53>": "GetHTTPTranslated",
"<7,54>": "GetHTTPRemoteAddr",
"<7,55>": "GetHTTPRemoteHost",
"<7,56>": "GetHTTPRemoteIdent",
"<7,57>": "GetHTTPRemoteUser",
"<7,58>": "GetHTTPRequestMethod",
"<7,59>": "GetHTTPScriptName",
"<7,60>": "GetHTTPServerName",
"<7,61>": "GetHTTPServerPort",
"<7,62>": "GetHTTPServerProtocol",
"<7,63>": "GetHTTPServerSoftware",
"<7,64>": "GetHTTPServerURL",
"<7,65>": "GetHTTPNoURLDecode",
"<7,66>": "GetHTTPResponseIsBinary",
"<7,67>": "GetHTTPRegistrySettings",
"<7,68>": "GetHTTPOECGIVersion",
"<7,69>": "GetHTTPGetString",
"<7,70>": "GetHTTPPostString",
"<7,71>": "GetHTTPAdditionalValues",
"<7,72>": "SetRequestHeaderFields",
"<7,73>": "SetRequestHeaderField",
"<7,74>": "GetRequestHeaderFields",
"<7,75>": "GetRequestHeaderField",
"<7,76>": "SetQueryFields",
"<7,77>": "SetQueryField",
"<7,78>": "GetQueryField",
"<7,79>": "SetResponseHeaderField",
"<7,80>": "SetCookie",
"<7,81>": "GetResponseHeaderFields",
"<7,82>": "GetResponseHeaderField",
"<7,83>": "SetResponseStatus",
"<7,84>": "GetResponseStatus",
"<7,85>": "SetResponseBody",
"<7,86>": "GetResponseBody",
"<7,87>": "GetResponseBodyIsBinary",
"<7,88>": "GetResponse",
"<7,89>": "SetResponseError",
"<7,90>": "GetErrorResponse",
"<7,91>": "DecodePercentString",
"<7,92>": "ClearSettings",
"<7,93>": "GetHomeURL",
"<7,94>": "GetAPIRootURL",
"<7,95>": "GetCapturePath",
"<7,96>": "GetRealmValue",
"<7,97>": "GetEntryPointService",
"<7,98>": "GetVersion",
"<7,99>": "GetFullEndpointURL",
"<7,100>": "GetFlushCacheFlag",
"<7,101>": "GetEnableAuthenticationFlag",
"<7,102>": "GetEnableHTTPBasicAuthenticationFlag",
"<7,103>": "GetNewPasswordTimeToLive",
"<7,104>": "GetOldPasswordTimeToLive",
"<7,105>": "GetInvalidPasswordLimit",
"<7,106>": "GetContainmentAction",
"<7,107>": "SetServerEnabled",
"<7,108>": "GetServerEnabled",
"<7,109>": "SetTotalInvalidPasswordAttempts",
"<7,110>": "GetTotalInvalidPasswordAttempts",
"<7,111>": "GetNonAuthenticatedPaths",
"<7,112>": "URLRequiresAuthentication",
"<7,113>": "GetWhitelistedIPs",
"<7,114>": "IsIPWhitelisted",
"<7,115>": "GetWhitelistedIPsType",
"<7,116>": "GetBannedIPs",
"<7,117>": "IsIPBanned",
"<7,118>": "AddBannedIP",
"<7,119>": "RemoveBannedIP",
"<7,120>": "IsIPPermitted",
"<7,121>": "IPIsPermitted",
"<7,122>": "GetBestContentNegotiation",
"<7,123>": "GetAbortedService",
"<7,124>": "GetEnableLoggingFlag",
"<7,125>": "GetLogErrorsOnlyFlag",
"<7,126>": "GetDebuggerSetting",
"<7,127>": "GetDebuggerService",
"<7,128>": "GetAPICallProcedure",
"<7,129>": "GetWebAPI",
"<7,130>": "UpdateWebAPIs",
"<7,131>": "GetLocalAppKeyID",
"<7,132>": "GetEndpoint",
"<7,133>": "IsValidEndpoint",
"<7,134>": "SetSupportedEndpoints",
"<7,135>": "GetEndpointPattern"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "Method",
"<8,1,2>": "Endpoint"
},
"<8,2>": {
"<8,2,1>": "HTTPService",
"<8,2,2>": "RemainingURL"
},
"<8,3>": "SelfURL",
"<8,4>": "",
"<8,5>": "",
"<8,6>": "",
"<8,7>": {
"<8,7,1>": "LogType",
"<8,7,2>": "Data"
},
"<8,8>": "Request",
"<8,9>": "",
"<8,10>": "ProcErr",
"<8,11>": "",
"<8,12>": "HTTPValue",
"<8,13>": "HTTPValue",
"<8,14>": "HTTPValue",
"<8,15>": "HTTPValue",
"<8,16>": "HTTPValue",
"<8,17>": "HTTPValue",
"<8,18>": "HTTPValue",
"<8,19>": "HTTPValue",
"<8,20>": "HTTPValue",
"<8,21>": "HTTPValue",
"<8,22>": "HTTPValue",
"<8,23>": "HTTPValue",
"<8,24>": "HTTPValue",
"<8,25>": "HTTPValue",
"<8,26>": "HTTPValue",
"<8,27>": "HTTPValue",
"<8,28>": "HTTPValue",
"<8,29>": "HTTPValue",
"<8,30>": "HTTPValue",
"<8,31>": "HTTPValue",
"<8,32>": "HTTPValue",
"<8,33>": "HTTPValue",
"<8,34>": "HTTPValue",
"<8,35>": "HTTPValue",
"<8,36>": "HTTPValue",
"<8,37>": "HTTPValue",
"<8,38>": "HTTPValue",
"<8,39>": "HTTPValue",
"<8,40>": "HTTPValue",
"<8,41>": "HTTPValue",
"<8,42>": "DecodePercentString",
"<8,43>": "DecodePercentString",
"<8,44>": "DecodePercentString",
"<8,45>": "DecodePercentString",
"<8,46>": "DecodePercentString",
"<8,47>": "DecodePercentString",
"<8,48>": "DecodePercentString",
"<8,49>": "DecodePercentString",
"<8,50>": "DecodePercentString",
"<8,51>": "DecodePercentString",
"<8,52>": "DecodePercentString",
"<8,53>": "DecodePercentString",
"<8,54>": "DecodePercentString",
"<8,55>": "DecodePercentString",
"<8,56>": "DecodePercentString",
"<8,57>": "DecodePercentString",
"<8,58>": "DecodePercentString",
"<8,59>": "DecodePercentString",
"<8,60>": "DecodePercentString",
"<8,61>": "DecodePercentString",
"<8,62>": "DecodePercentString",
"<8,63>": "DecodePercentString",
"<8,64>": "DecodePercentString",
"<8,65>": "DecodePercentString",
"<8,66>": "DecodePercentString",
"<8,67>": "DecodePercentString",
"<8,68>": "DecodePercentString",
"<8,69>": "DecodePercentString",
"<8,70>": "DecodePercentString",
"<8,71>": "DecodePercentString",
"<8,72>": "",
"<8,73>": {
"<8,73,1>": "Name",
"<8,73,2>": "Value"
},
"<8,74>": "",
"<8,75>": "Name",
"<8,76>": "",
"<8,77>": {
"<8,77,1>": "Field",
"<8,77,2>": "Value"
},
"<8,78>": "Field",
"<8,79>": {
"<8,79,1>": "Name",
"<8,79,2>": "Value",
"<8,79,3>": "Append"
},
"<8,80>": {
"<8,80,1>": "Name",
"<8,80,2>": "Value",
"<8,80,3>": "Expires",
"<8,80,4>": "MaxAge",
"<8,80,5>": "Domain",
"<8,80,6>": "Path",
"<8,80,7>": "Secure",
"<8,80,8>": "HttpOnly",
"<8,80,9>": "Extension"
},
"<8,81>": "",
"<8,82>": "Name",
"<8,83>": {
"<8,83,1>": "Code",
"<8,83,2>": "Phrase"
},
"<8,84>": "",
"<8,85>": {
"<8,85,1>": "Body",
"<8,85,2>": "IsBinary",
"<8,85,3>": "ContentType"
},
"<8,86>": "",
"<8,87>": "",
"<8,88>": "",
"<8,89>": {
"<8,89,1>": "TypeURL",
"<8,89,2>": "Title",
"<8,89,3>": "Status",
"<8,89,4>": "Detail",
"<8,89,5>": "InstanceURL",
"<8,89,6>": "PropertyNames",
"<8,89,7>": "PropertyValues"
},
"<8,90>": "",
"<8,91>": "String",
"<8,92>": "",
"<8,93>": "",
"<8,94>": "FullURL",
"<8,95>": "",
"<8,96>": "",
"<8,97>": "",
"<8,98>": "",
"<8,99>": "",
"<8,100>": "",
"<8,101>": "",
"<8,102>": "",
"<8,103>": "",
"<8,104>": "",
"<8,105>": "",
"<8,106>": "",
"<8,107>": "ServerEnabled",
"<8,108>": "",
"<8,109>": "Attempts",
"<8,110>": "",
"<8,111>": "",
"<8,112>": "URL",
"<8,113>": "",
"<8,114>": "IP",
"<8,115>": "",
"<8,116>": "",
"<8,117>": "IP",
"<8,118>": "IP",
"<8,119>": "IP",
"<8,120>": "IP",
"<8,121>": "IP",
"<8,122>": {
"<8,122,1>": "RequestHeaderField",
"<8,122,2>": "ServerOptions"
},
"<8,123>": "",
"<8,124>": "",
"<8,125>": "",
"<8,126>": "",
"<8,127>": "",
"<8,128>": "",
"<8,129>": {
"<8,129,1>": "Resource",
"<8,129,2>": "ReturnRepositoryKeyID"
},
"<8,130>": {
"<8,130,1>": "ResourceList",
"<8,130,2>": "MakeLocal"
},
"<8,131>": "BaseAppKeyID",
"<8,132>": "",
"<8,133>": "Endpoint",
"<8,134>": "",
"<8,135>": "Endpoint"
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": ""
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": ""
},
"<9,3>": "",
"<9,4>": "",
"<9,5>": "",
"<9,6>": "",
"<9,7>": {
"<9,7,1>": "LOGTYPES",
"<9,7,2>": ""
},
"<9,8>": "",
"<9,9>": "",
"<9,10>": "",
"<9,11>": "",
"<9,12>": "",
"<9,13>": "",
"<9,14>": "",
"<9,15>": "",
"<9,16>": "",
"<9,17>": "",
"<9,18>": "",
"<9,19>": "",
"<9,20>": "",
"<9,21>": "",
"<9,22>": "",
"<9,23>": "",
"<9,24>": "",
"<9,25>": "",
"<9,26>": "",
"<9,27>": "",
"<9,28>": "",
"<9,29>": "",
"<9,30>": "",
"<9,31>": "",
"<9,32>": "",
"<9,33>": "",
"<9,34>": "",
"<9,35>": "",
"<9,36>": "",
"<9,37>": "",
"<9,38>": "",
"<9,39>": "",
"<9,40>": "",
"<9,41>": "",
"<9,42>": "",
"<9,43>": "",
"<9,44>": "",
"<9,45>": "",
"<9,46>": "",
"<9,47>": "",
"<9,48>": "",
"<9,49>": "",
"<9,50>": "",
"<9,51>": "",
"<9,52>": "",
"<9,53>": "",
"<9,54>": "",
"<9,55>": "",
"<9,56>": "",
"<9,57>": "",
"<9,58>": "",
"<9,59>": "",
"<9,60>": "",
"<9,61>": "",
"<9,62>": "",
"<9,63>": "",
"<9,64>": "",
"<9,65>": "",
"<9,66>": "",
"<9,67>": "",
"<9,68>": "",
"<9,69>": "",
"<9,70>": "",
"<9,71>": "",
"<9,72>": "",
"<9,73>": {
"<9,73,1>": "",
"<9,73,2>": ""
},
"<9,74>": "",
"<9,75>": "",
"<9,76>": "",
"<9,77>": {
"<9,77,1>": "",
"<9,77,2>": ""
},
"<9,78>": "",
"<9,79>": {
"<9,79,1>": "RESPONSEHEADERNAMES",
"<9,79,2>": "",
"<9,79,3>": "BOOLEAN"
},
"<9,80>": {
"<9,80,1>": "",
"<9,80,2>": "",
"<9,80,3>": "",
"<9,80,4>": "",
"<9,80,5>": "",
"<9,80,6>": "",
"<9,80,7>": "BOOLEAN",
"<9,80,8>": "BOOLEAN",
"<9,80,9>": ""
},
"<9,81>": "",
"<9,82>": "RESPONSEHEADERNAMES",
"<9,83>": {
"<9,83,1>": "",
"<9,83,2>": ""
},
"<9,84>": "",
"<9,85>": {
"<9,85,1>": "",
"<9,85,2>": "",
"<9,85,3>": ""
},
"<9,86>": "",
"<9,87>": "",
"<9,88>": "",
"<9,89>": {
"<9,89,1>": "",
"<9,89,2>": "",
"<9,89,3>": "",
"<9,89,4>": "",
"<9,89,5>": "",
"<9,89,6>": "",
"<9,89,7>": ""
},
"<9,90>": "",
"<9,91>": "",
"<9,92>": "",
"<9,93>": "",
"<9,94>": "BOOLEAN",
"<9,95>": "",
"<9,96>": "",
"<9,97>": "",
"<9,98>": "",
"<9,99>": "",
"<9,100>": "",
"<9,101>": "",
"<9,102>": "",
"<9,103>": "",
"<9,104>": "",
"<9,105>": "",
"<9,106>": "",
"<9,107>": "BOOLEAN",
"<9,108>": "",
"<9,109>": "",
"<9,110>": "",
"<9,111>": "",
"<9,112>": "",
"<9,113>": "",
"<9,114>": "",
"<9,115>": "",
"<9,116>": "",
"<9,117>": "",
"<9,118>": "",
"<9,119>": "",
"<9,120>": "",
"<9,121>": "",
"<9,122>": {
"<9,122,1>": "CONTENTNEGOTIATIONFIELDS",
"<9,122,2>": ""
},
"<9,123>": "",
"<9,124>": "",
"<9,125>": "",
"<9,126>": "",
"<9,127>": "",
"<9,128>": "",
"<9,129>": {
"<9,129,1>": "",
"<9,129,2>": ""
},
"<9,130>": {
"<9,130,1>": "",
"<9,130,2>": "BOOLEAN"
},
"<9,131>": "",
"<9,132>": "",
"<9,133>": "",
"<9,134>": "",
"<9,135>": ""
},
"<10>": {
"<10,1>": "BOOLEAN",
"<10,2>": "RESPONSEHEADERNAMES",
"<10,3>": "CONTENTNEGOTIATIONFIELDS",
"<10,4>": "LOGTYPES"
},
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
},
"<11,2>": {
"<11,2,1>": "Access-Control-Allow-Headers",
"<11,2,2>": "Access-Control-Allow-Methods",
"<11,2,3>": "Access-Control-Allow-Origin",
"<11,2,4>": "Allow",
"<11,2,5>": "Content-Encoding",
"<11,2,6>": "Content-Language",
"<11,2,7>": "Content-Length",
"<11,2,8>": "Content-Location",
"<11,2,9>": "Content-Disposition",
"<11,2,10>": "Content-Type",
"<11,2,11>": "Date",
"<11,2,12>": "Expires",
"<11,2,13>": "Last-Modified",
"<11,2,14>": "Link",
"<11,2,15>": "Location",
"<11,2,16>": "Retry-After",
"<11,2,17>": "Server",
"<11,2,18>": "Set-Cookie",
"<11,2,19>": "Transfer-Encoding",
"<11,2,20>": "Vary",
"<11,2,21>": "WWW-Authenticate"
},
"<11,3>": {
"<11,3,1>": "Accept",
"<11,3,2>": "Accept-Charset",
"<11,3,3>": "Accept-Encoding",
"<11,3,4>": "Accept-Language"
},
"<11,4>": {
"<11,4,1>": "Request",
"<11,4,2>": "Response",
"<11,4,3>": "Aborted",
"<11,4,4>": "Debugger"
}
},
"<12>": {
"<12,1>": "0",
"<12,2>": "1",
"<12,3>": "1",
"<12,4>": "1"
}
}
}
}

View File

@ -0,0 +1,99 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*LOGGING_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "NewLog",
"<7,2>": "AppendLog",
"<7,3>": "GetLogPath",
"<7,4>": "GetLogFileName",
"<7,5>": "GetLogFullPath",
"<7,6>": "GetRowDelimiter",
"<7,7>": "GetColumnDelimiter",
"<7,8>": "GetColumnHeaders",
"<7,9>": "GetColumnWidths",
"<7,10>": "GetQuoteValues",
"<7,11>": "CreateLogFile"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "LogPath",
"<8,1,2>": "LogFileName",
"<8,1,3>": "RowDelimiter",
"<8,1,4>": "ColumnDelimiter",
"<8,1,5>": "ColumnHeaders",
"<8,1,6>": "ColumnWidths",
"<8,1,7>": "QuoteValues",
"<8,1,8>": "ClearLog"
},
"<8,2>": {
"<8,2,1>": "objLog",
"<8,2,2>": "LogData",
"<8,2,3>": "IncomingRowDelimiter",
"<8,2,4>": "IncomingColumnDelimiter",
"<8,2,5>": "IgnoreColumnHeaders"
},
"<8,3>": "objLog",
"<8,4>": "objLog",
"<8,5>": "objLog",
"<8,6>": "objLog",
"<8,7>": "objLog",
"<8,8>": "objLog",
"<8,9>": "objLog",
"<8,10>": "objLog",
"<8,11>": "objLog"
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": "",
"<9,1,3>": "",
"<9,1,4>": "",
"<9,1,5>": "",
"<9,1,6>": "",
"<9,1,7>": "BOOLEAN",
"<9,1,8>": "BOOLEAN"
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": "",
"<9,2,3>": "",
"<9,2,4>": "",
"<9,2,5>": ""
},
"<9,3>": "",
"<9,4>": "",
"<9,5>": "",
"<9,6>": "",
"<9,7>": "",
"<9,8>": "",
"<9,9>": "",
"<9,10>": "",
"<9,11>": ""
},
"<10>": "BOOLEAN",
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
}
},
"<12>": "0"
}
}
}

View File

@ -0,0 +1,116 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*MEMORY_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "KeyExists",
"<7,2>": "GetValue",
"<7,3>": "SetValue",
"<7,4>": "IsValueExpired",
"<7,5>": "IsValueCurrent",
"<7,6>": "RemoveKey",
"<7,7>": "CreateHashTable",
"<7,8>": "ReleaseHashTable",
"<7,9>": "ReleaseAllHashTables",
"<7,10>": "GetHandle"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "KeyID",
"<8,1,2>": "CacheName"
},
"<8,2>": {
"<8,2,1>": "KeyID",
"<8,2,2>": "NotExpired",
"<8,2,3>": "ExpirationDuration",
"<8,2,4>": "CacheName"
},
"<8,3>": {
"<8,3,1>": "KeyID",
"<8,3,2>": "Value",
"<8,3,3>": "CacheName"
},
"<8,4>": {
"<8,4,1>": "KeyID",
"<8,4,2>": "ExpirationDuration",
"<8,4,3>": "ResetAge",
"<8,4,4>": "CacheName"
},
"<8,5>": {
"<8,5,1>": "KeyID",
"<8,5,2>": "ExpirationDuration",
"<8,5,3>": "ResetAge",
"<8,5,4>": "CacheName"
},
"<8,6>": {
"<8,6,1>": "KeyID",
"<8,6,2>": "CacheName"
},
"<8,7>": "CacheName",
"<8,8>": "CacheName",
"<8,9>": "CacheName",
"<8,10>": "CacheName"
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": ""
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": "",
"<9,2,3>": "",
"<9,2,4>": ""
},
"<9,3>": {
"<9,3,1>": "",
"<9,3,2>": "",
"<9,3,3>": ""
},
"<9,4>": {
"<9,4,1>": "",
"<9,4,2>": "",
"<9,4,3>": "",
"<9,4,4>": ""
},
"<9,5>": {
"<9,5,1>": "",
"<9,5,2>": "",
"<9,5,3>": "",
"<9,5,4>": ""
},
"<9,6>": {
"<9,6,1>": "",
"<9,6,2>": ""
},
"<9,7>": "",
"<9,8>": "",
"<9,9>": "",
"<9,10>": ""
},
"<10>": "BOOLEAN",
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
}
},
"<12>": "0"
}
}
}

View File

@ -0,0 +1,23 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*OATH_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": "oath.GET",
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,27 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*PICTURE_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "picture.GET",
"<7,2>": "picture.HEAD",
"<7,3>": "picture.PUT"
},
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,26 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*PING_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "ping.HEAD",
"<7,2>": "ping.GET"
},
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,26 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*VERSION_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "version.HEAD",
"<7,2>": "version.GET"
},
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,31 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*WEBACCOUNTS_API*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "API",
"<2>": "@API",
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "webaccounts.HEAD",
"<7,2>": "webaccounts.GET",
"<7,3>": "webaccounts.ID.HEAD",
"<7,4>": "webaccounts.ID.GET",
"<7,5>": "webaccounts.ID.password.HEAD",
"<7,6>": "webaccounts.ID.password.GET",
"<7,7>": "webaccounts.ID.password.PATCH"
},
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": "",
"<12>": ""
}
}
}

View File

@ -0,0 +1,68 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_EDITOR_METADATA*WEBACCOUNTS_SERVICES*FRAMEWORKS"
},
"body": {
"record1": {
"<1>": "SERVICE",
"<2>": {
"<2,1>": {
"<2,1,1>": "@Service",
"<2,1,2>": "@Params"
}
},
"<3>": "1",
"<4>": "2",
"<5>": "1",
"<6>": "",
"<7>": {
"<7,1>": "GetWebAccounts",
"<7,2>": "SetWebAccounts",
"<7,3>": "ConvertMVWebAccountsToJSON",
"<7,4>": "ConvertJSONWebAccountsToMV"
},
"<8>": {
"<8,1>": {
"<8,1,1>": "AccountID",
"<8,1,2>": "ReturnJSON"
},
"<8,2>": {
"<8,2,1>": "AccountID",
"<8,2,2>": "WebAccountsRow"
},
"<8,3>": {
"<8,3,1>": "AccountID",
"<8,3,2>": "mvWebAccounts",
"<8,3,3>": "itemURL"
},
"<8,4>": "jsonWebAccounts"
},
"<9>": {
"<9,1>": {
"<9,1,1>": "",
"<9,1,2>": ""
},
"<9,2>": {
"<9,2,1>": "",
"<9,2,2>": ""
},
"<9,3>": {
"<9,3,1>": "",
"<9,3,2>": "",
"<9,3,3>": ""
},
"<9,4>": ""
},
"<10>": "BOOLEAN",
"<11>": {
"<11,1>": {
"<11,1,1>": "True$",
"<11,1,2>": "False$"
}
},
"<12>": "0"
}
}
}

View File

@ -0,0 +1,154 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_HTTP_LOGS_ARCHIVE_SCRIPT"
},
"body": {
"record1": {
"<1>": "",
"<2>": "function Archive-SRPHTTPLogs {",
"<3>": "param(",
"<4>": " [string]$OlderThanDateStr = \"\",",
"<5>": " [string]$LogPathSource = \"C:\\httplogs\",",
"<6>": " [string]$LogPathDest = \"c:\\httplogs\\archive\"",
"<7>": ")",
"<8>": "$progresspreference=\"SilentlyContinue\";",
"<9>": "",
"<10>": "#Uncomment this to simulate an error",
"<11>": "#Blah $Failed;",
"<12>": "",
"<13>": "if($OlderThanDateStr -ne \"\") {",
"<14>": " #Convert the supplied date to an object",
"<15>": " #Throws error if not a valid date",
"<16>": "",
"<17>": " try {",
"<18>": " $OlderThanDate = [datetime]$OlderThanDateStr;",
"<19>": " } catch {",
"<20>": " throw $_;",
"<21>": " return;",
"<22>": " }",
"<23>": "}",
"<24>": "",
"<25>": "#What files in $LogPathSource are considered to be log files?",
"<26>": "$LogExtension = \"*.log\";",
"<27>": "",
"<28>": "#Check the organized folder exists",
"<29>": "New-Item -Path $LogPathDest -ItemType \"directory\" -Force | Out-Null;",
"<30>": "",
"<31>": "#Get all the files to be organized",
"<32>": "$LogFiles = Get-ChildItem -Path $LogPathSource -Filter $LogExtension;",
"<33>": "",
"<34>": "#Store a hash table of dates from file names",
"<35>": "$LogDates = @{};",
"<36>": "",
"<37>": "#Loop through all the files and organize them by date",
"<38>": "ForEach($LogFile in $LogFiles) {",
"<39>": "",
"<40>": " $FileName = $LogFile.Name;",
"<41>": "",
"<42>": "\t#Doesn't work on Server 2008",
"<43>": " #$FileNameDate = [regex]::Match($FileName,'^(.*?)_').captures.groups[1].value;",
"<44>": "\t",
"<45>": "\t#Works in Server 2008",
"<46>": "\t$FileNameDate = $FileName.Split('_')[0];",
"<47>": "",
"<48>": " $FileNameDateObj = $Null;",
"<49>": "",
"<50>": " try {",
"<51>": " $FileNameDateObj = [datetime]$FileNameDate;",
"<52>": " } catch {",
"<53>": " #This was not a valid date so skip",
"<54>": " }",
"<55>": "",
"<56>": " if ($FileNameDateObj -ne $Null) {",
"<57>": " #This filename has a valid date",
"<58>": "",
"<59>": " #Is it within our range?",
"<60>": " if($FileNameDateObj -le $OlderThanDate) {",
"<61>": " #Yes, the file name is old enough to archive",
"<62>": "",
"<63>": "\t #Have we seen this date before?",
"<64>": " if ($LogDates[$FileNameDate] -eq $null) {",
"<65>": "\t\t #No, so create an array list and store it in the hash table under the date key",
"<66>": " #Write-Host \"Found logs for new date: $FileNameDate\";",
"<67>": " [System.Collections.ArrayList]$NewArray = @($FileName);",
"<68>": " $LogDates[$FileNameDate] = \t$NewArray;",
"<69>": " } else {",
"<70>": "\t\t # Yes, so add it to the array of filenames for that date",
"<71>": " # Write-Host \"Adding $FileNameDate\";",
"<72>": " $LogDates[$FileNameDate].Add($FileName) | Out-Null;",
"<73>": " }",
"<74>": "",
"<75>": " } else {",
"<76>": " #No, the file name is newer than our cut-off date",
"<77>": " }",
"<78>": "",
"<79>": " } else {",
"<80>": " #The file name did not have a valid date entry in the filename so skip",
"<81>": " }",
"<82>": "",
"<83>": "}",
"<84>": "",
"<85>": "#Loop through the hashtable of all the dates seen",
"<86>": "#and process the arraylist of files for that date",
"<87>": "ForEach($LogDate In $LogDates.keys) {",
"<88>": "",
"<89>": " #Write-Host \"Processing log dates $LogDate\";",
"<90>": "",
"<91>": " $LogFolderForDate = $LogPathDest + \"\\\" + $LogDate;",
"<92>": "",
"<93>": "\t#Make sure the organization folder exists",
"<94>": " New-Item -Path $LogFolderForDate -ItemType \"directory\" -Force | Out-Null;",
"<95>": "",
"<96>": " $LogFilesForDate = $LogDates[$LogDate];",
"<97>": "",
"<98>": "\t#Loop through all the files for that date",
"<99>": " ForEach ($LogFileName in $LogFilesForDate) {",
"<100>": "",
"<101>": " $Src = $LogPathSource + \"\\\" + $LogFileName;",
"<102>": " $Dst = $LogFolderForDate + \"\\\" + $LogFileName;",
"<103>": "",
"<104>": " #Write-Host \"Moving $Src to $Dst\";",
"<105>": " Move-Item -Path $Src -Destination $Dst -Force;",
"<106>": "",
"<107>": " }",
"<108>": "",
"<109>": "}",
"<110>": "",
"<111>": "#Loop through the hashtable of all the dates seen",
"<112>": "#and compress the files that were organized into folders",
"<113>": "ForEach($LogDate In $LogDates.keys) {",
"<114>": "",
"<115>": " #Figure out which archive date we want to compress",
"<116>": " $LogFolderForDate = $LogPathDest + \"\\\" + $LogDate;",
"<117>": "",
"<118>": " #The name of the zip file where the archived date should reside",
"<119>": " $LogFolderZipFile = $LogPathDest + \"\\\" + $LogDate + \".zip\"",
"<120>": "",
"<121>": " try {",
"<122>": " #Compress it, fail if any error",
"<123>": " Compress-Archive -Path $($LogFolderForDate + \"\\\" + $LogExtension) -DestinationPath $LogFolderZipFile -ErrorAction Stop",
"<124>": "",
"<125>": " #Remove the source log files",
"<126>": " Remove-Item -Path $LogFolderForDate -Recurse -Force",
"<127>": " } catch {",
"<128>": " throw $_;",
"<129>": " return",
"<130>": " }",
"<131>": " ",
"<132>": "}",
"<133>": "",
"<134>": "",
"<135>": "",
"<136>": "} #End Archive-SRPHTTPLogs",
"<137>": "",
"<138>": "try {",
"<139>": " Archive-SRPHTTPLogs -OlderThanDate '{{ArchiveOlderThanDate}}' -LogPathSource '{{ArchiveLogsFromFolder}}' -LogPathDest '{{ArchiveStorageFolder}}';",
"<140>": " Return \"OK\";",
"<141>": "} catch {",
"<142>": " Return \"ERROR`n\" + $_.ToString() ;",
"<143>": "}"
}
}
}

View File

@ -0,0 +1,135 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_HTTP_STATUS_CODES"
},
"body": {
"record1": {
"<1>": {
"<1,1>": "100",
"<1,2>": "101",
"<1,3>": "102",
"<1,4>": "200",
"<1,5>": "201",
"<1,6>": "202",
"<1,7>": "203",
"<1,8>": "204",
"<1,9>": "205",
"<1,10>": "206",
"<1,11>": "207",
"<1,12>": "208",
"<1,13>": "226",
"<1,14>": "300",
"<1,15>": "301",
"<1,16>": "302",
"<1,17>": "303",
"<1,18>": "304",
"<1,19>": "305",
"<1,20>": "306",
"<1,21>": "307",
"<1,22>": "308",
"<1,23>": "400",
"<1,24>": "401",
"<1,25>": "402",
"<1,26>": "403",
"<1,27>": "404",
"<1,28>": "405",
"<1,29>": "406",
"<1,30>": "407",
"<1,31>": "408",
"<1,32>": "409",
"<1,33>": "410",
"<1,34>": "411",
"<1,35>": "412",
"<1,36>": "413",
"<1,37>": "414",
"<1,38>": "415",
"<1,39>": "416",
"<1,40>": "417",
"<1,41>": "418",
"<1,42>": "421",
"<1,43>": "422",
"<1,44>": "423",
"<1,45>": "424",
"<1,46>": "426",
"<1,47>": "428",
"<1,48>": "429",
"<1,49>": "431",
"<1,50>": "500",
"<1,51>": "501",
"<1,52>": "502",
"<1,53>": "503",
"<1,54>": "504",
"<1,55>": "505",
"<1,56>": "506",
"<1,57>": "507",
"<1,58>": "508",
"<1,59>": "510",
"<1,60>": "511"
},
"<2>": {
"<2,1>": "Continue",
"<2,2>": "Switching Protocols",
"<2,3>": "Processing (WebDAV; RFC 2518)",
"<2,4>": "OK",
"<2,5>": "Created",
"<2,6>": "Accepted",
"<2,7>": "Non-Authoritative Information (since HTTP/1.1)",
"<2,8>": "No Content",
"<2,9>": "Reset Content",
"<2,10>": "Partial Content (RFC 7233)",
"<2,11>": "Multi-Status (WebDAV; RFC 4918)",
"<2,12>": "Already Reported (WebDAV; RFC 5842)",
"<2,13>": "IM Used (RFC 3229)",
"<2,14>": "Multiple Choices",
"<2,15>": "Moved Permanently",
"<2,16>": "Found",
"<2,17>": "See Other (since HTTP/1.1)",
"<2,18>": "Not Modified (RFC 7232)",
"<2,19>": "Use Proxy (since HTTP/1.1)",
"<2,20>": "Switch Proxy",
"<2,21>": "Temporary Redirect (since HTTP/1.1)",
"<2,22>": "Permanent Redirect (RFC 7538)",
"<2,23>": "Bad Request",
"<2,24>": "Unauthorized (RFC 7235)",
"<2,25>": "Payment Required",
"<2,26>": "Forbidden",
"<2,27>": "Not Found",
"<2,28>": "Method Not Allowed",
"<2,29>": "Not Acceptable",
"<2,30>": "Proxy Authentication Required (RFC 7235)",
"<2,31>": "Request Timeout",
"<2,32>": "Conflict",
"<2,33>": "Gone",
"<2,34>": "Length Required",
"<2,35>": "Precondition Failed (RFC 7232)",
"<2,36>": "Payload Too Large (RFC 7231)",
"<2,37>": "URI Too Long (RFC 7231)",
"<2,38>": "Unsupported Media Type",
"<2,39>": "Range Not Satisfiable (RFC 7233)",
"<2,40>": "Expectation Failed",
"<2,41>": "I'm a teapot (RFC 2324)",
"<2,42>": "Misdirected Request (RFC 7540)",
"<2,43>": "Unprocessable Entity (WebDAV; RFC 4918)",
"<2,44>": "Locked (WebDAV; RFC 4918)",
"<2,45>": "Failed Dependency (WebDAV; RFC 4918)",
"<2,46>": "Upgrade Required",
"<2,47>": "Precondition Required (RFC 6585)",
"<2,48>": "Too Many Requests (RFC 6585)",
"<2,49>": "Request Header Fields Too Large (RFC 6585)",
"<2,50>": "Internal Server Error",
"<2,51>": "Not Implemented",
"<2,52>": "Bad Gateway",
"<2,53>": "Service Unavailable",
"<2,54>": "Gateway Timeout",
"<2,55>": "HTTP Version Not Supported",
"<2,56>": "Variant Also Negotiates (RFC 2295)",
"<2,57>": "Insufficient Storage (WebDAV; RFC 4918)",
"<2,58>": "Loop Detected (WebDAV; RFC 5842)",
"<2,59>": "Not Extended (RFC 2774)",
"<2,60>": "Network Authentication Required (RFC 6585)"
}
}
}
}

View File

@ -0,0 +1,863 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_RESOURCES"
},
"body": {
"record1": {
"<1>": {
"<1,1>": "1",
"<1,2>": "APIROOT",
"<1,3>": "api",
"<1,4>": {
"<1,4,1>": "Text",
"<1,4,2>": ""
},
"<1,5>": "APIROOT",
"<1,6>": "",
"<1,7>": {
"<1,7,1>": "RGB{68, 68, 68}",
"<1,7,2>": "White"
},
"<1,8>": {
"<1,8,1>": "Segoe UI",
"<1,8,2>": "-12",
"<1,8,3>": "400",
"<1,8,4>": "0",
"<1,8,5>": "0",
"<1,8,6>": "0",
"<1,8,7>": "1",
"<1,8,8>": "0",
"<1,8,9>": "0",
"<1,8,10>": "0",
"<1,8,11>": "0",
"<1,8,12>": "0"
},
"<1,9>": {
"<1,9,1>": "Left",
"<1,9,2>": "Center"
},
"<1,10>": "N",
"<1,11>": "None",
"<1,12>": "1",
"<1,13>": "24",
"<1,14>": "0",
"<1,15>": "1",
"<1,16>": "None",
"<1,17>": "Left",
"<1,18>": {
"<1,18,1>": "13",
"<1,18,2>": "13"
},
"<1,19>": {
"<1,19,1>": {
"<1,19,1,1>": "DESCRIPTION",
"<1,19,1,2>": "This is the API entry point."
},
"<1,19,2>": {
"<1,19,2,1>": "API_SIGNATURES",
"<1,19,2,2>": "APIROOT.GET"
},
"<1,19,3>": {
"<1,19,3,1>": "EXCLUDE_LOGGING",
"<1,19,3,2>": "0"
},
"<1,19,4>": {
"<1,19,4,1>": "METHODS",
"<1,19,4,2>": "GET"
},
"<1,19,5>": {
"<1,19,5,1>": "QUERY_PARAMS",
"<1,19,5,2>": ""
},
"<1,19,6>": {
"<1,19,6,1>": "TITLE",
"<1,19,6,2>": "API Entry Point"
}
}
},
"<2>": {
"<2,1>": "2",
"<2,2>": "/webaccounts",
"<2,3>": "webaccounts",
"<2,4>": {
"<2,4,1>": "Text",
"<2,4,2>": ""
},
"<2,5>": "RESOURCE",
"<2,6>": "",
"<2,7>": {
"<2,7,1>": "RGB{68, 68, 68}",
"<2,7,2>": "White"
},
"<2,8>": {
"<2,8,1>": "Segoe UI",
"<2,8,2>": "-12",
"<2,8,3>": "400",
"<2,8,4>": "0",
"<2,8,5>": "0",
"<2,8,6>": "0",
"<2,8,7>": "1",
"<2,8,8>": "0",
"<2,8,9>": "0",
"<2,8,10>": "0",
"<2,8,11>": "0",
"<2,8,12>": "0"
},
"<2,9>": {
"<2,9,1>": "Left",
"<2,9,2>": "Center"
},
"<2,10>": "N",
"<2,11>": "None",
"<2,12>": "1",
"<2,13>": "24",
"<2,14>": "0",
"<2,15>": "1",
"<2,16>": "None",
"<2,17>": "Left",
"<2,18>": {
"<2,18,1>": "13",
"<2,18,2>": "13"
},
"<2,19>": {
"<2,19,1>": {
"<2,19,1,1>": "DESCRIPTION",
"<2,19,1,2>": "Web accounts resource used by the authentication service."
},
"<2,19,2>": {
"<2,19,2,1>": "API_SIGNATURES",
"<2,19,2,2>": "webaccounts.GET"
},
"<2,19,3>": {
"<2,19,3,1>": "EXCLUDE_LOGGING",
"<2,19,3,2>": "0"
},
"<2,19,4>": {
"<2,19,4,1>": "METHODS",
"<2,19,4,2>": "GET"
},
"<2,19,5>": {
"<2,19,5,1>": "QUERY_PARAMS",
"<2,19,5,2>": ""
},
"<2,19,6>": {
"<2,19,6,1>": "TITLE",
"<2,19,6,2>": "Web Accounts"
}
}
},
"<3>": {
"<3,1>": "3",
"<3,2>": "/webaccounts/{accountID}",
"<3,3>": "{accountID}",
"<3,4>": {
"<3,4,1>": "Text",
"<3,4,2>": ""
},
"<3,5>": "RESOURCE_ID",
"<3,6>": "",
"<3,7>": {
"<3,7,1>": "RGB{68, 68, 68}",
"<3,7,2>": "White"
},
"<3,8>": {
"<3,8,1>": "Segoe UI",
"<3,8,2>": "-12",
"<3,8,3>": "400",
"<3,8,4>": "0",
"<3,8,5>": "0",
"<3,8,6>": "0",
"<3,8,7>": "1",
"<3,8,8>": "0",
"<3,8,9>": "0",
"<3,8,10>": "0",
"<3,8,11>": "0",
"<3,8,12>": "0"
},
"<3,9>": {
"<3,9,1>": "Left",
"<3,9,2>": "Center"
},
"<3,10>": "N",
"<3,11>": "None",
"<3,12>": "1",
"<3,13>": "24",
"<3,14>": "0",
"<3,15>": "1",
"<3,16>": "None",
"<3,17>": "Left",
"<3,18>": {
"<3,18,1>": "13",
"<3,18,2>": "13"
},
"<3,19>": {
"<3,19,1>": {
"<3,19,1,1>": "DESCRIPTION",
"<3,19,1,2>": "Unique account ID for the web accounts resource."
},
"<3,19,2>": {
"<3,19,2,1>": "API_SIGNATURES",
"<3,19,2,2>": "webaccounts.ID.GET"
},
"<3,19,3>": {
"<3,19,3,1>": "EXCLUDE_LOGGING",
"<3,19,3,2>": "0"
},
"<3,19,4>": {
"<3,19,4,1>": "METHODS",
"<3,19,4,2>": "GET"
},
"<3,19,5>": {
"<3,19,5,1>": "QUERY_PARAMS",
"<3,19,5,2>": ""
},
"<3,19,6>": {
"<3,19,6,1>": "TITLE",
"<3,19,6,2>": "Web Accounts ID"
}
}
},
"<4>": {
"<4,1>": "4",
"<4,2>": "/webaccounts/{accountID}/password",
"<4,3>": "password",
"<4,4>": {
"<4,4,1>": "Text",
"<4,4,2>": ""
},
"<4,5>": "PROPERTY",
"<4,6>": "",
"<4,7>": {
"<4,7,1>": "RGB{68, 68, 68}",
"<4,7,2>": "White"
},
"<4,8>": {
"<4,8,1>": "Segoe UI",
"<4,8,2>": "-12",
"<4,8,3>": "400",
"<4,8,4>": "0",
"<4,8,5>": "0",
"<4,8,6>": "0",
"<4,8,7>": "1",
"<4,8,8>": "0",
"<4,8,9>": "0",
"<4,8,10>": "0",
"<4,8,11>": "0",
"<4,8,12>": "0"
},
"<4,9>": {
"<4,9,1>": "Left",
"<4,9,2>": "Center"
},
"<4,10>": "N",
"<4,11>": "None",
"<4,12>": "1",
"<4,13>": "24",
"<4,14>": "0",
"<4,15>": "1",
"<4,16>": "None",
"<4,17>": "Left",
"<4,18>": {
"<4,18,1>": "13",
"<4,18,2>": "13"
},
"<4,19>": {
"<4,19,1>": {
"<4,19,1,1>": "DESCRIPTION",
"<4,19,1,2>": "Password property for the current web account."
},
"<4,19,2>": {
"<4,19,2,1>": "API_SIGNATURES",
"<4,19,2,2>": "webaccounts.ID.password.GET,webaccounts.ID.password.PATCH"
},
"<4,19,3>": {
"<4,19,3,1>": "EXCLUDE_LOGGING",
"<4,19,3,2>": "0"
},
"<4,19,4>": {
"<4,19,4,1>": "METHODS",
"<4,19,4,2>": "GET,PATCH"
},
"<4,19,5>": {
"<4,19,5,1>": "QUERY_PARAMS",
"<4,19,5,2>": ""
},
"<4,19,6>": {
"<4,19,6,1>": "TITLE",
"<4,19,6,2>": "Web Accounts Password"
}
}
},
"<5>": {
"<5,1>": "2",
"<5,2>": "/contacts",
"<5,3>": "contacts",
"<5,4>": {
"<5,4,1>": "Text",
"<5,4,2>": ""
},
"<5,5>": "RESOURCE",
"<5,6>": "",
"<5,7>": {
"<5,7,1>": "RGB{68, 68, 68}",
"<5,7,2>": "White"
},
"<5,8>": {
"<5,8,1>": "Segoe UI",
"<5,8,2>": "-12",
"<5,8,3>": "400",
"<5,8,4>": "0",
"<5,8,5>": "0",
"<5,8,6>": "0",
"<5,8,7>": "1",
"<5,8,8>": "0",
"<5,8,9>": "0",
"<5,8,10>": "0",
"<5,8,11>": "0",
"<5,8,12>": "0"
},
"<5,9>": {
"<5,9,1>": "Left",
"<5,9,2>": "Center"
},
"<5,10>": "N",
"<5,11>": "None",
"<5,12>": "1",
"<5,13>": "24",
"<5,14>": "0",
"<5,15>": "1",
"<5,16>": "None",
"<5,17>": "Left",
"<5,18>": {
"<5,18,1>": "13",
"<5,18,2>": "13"
},
"<5,19>": {
"<5,19,1>": {
"<5,19,1,1>": "DESCRIPTION",
"<5,19,1,2>": "Sample contacts resource."
},
"<5,19,2>": {
"<5,19,2,1>": "API_SIGNATURES",
"<5,19,2,2>": "contacts.POST,contacts.GET"
},
"<5,19,3>": {
"<5,19,3,1>": "EXCLUDE_LOGGING",
"<5,19,3,2>": "0"
},
"<5,19,4>": {
"<5,19,4,1>": "METHODS",
"<5,19,4,2>": "POST,GET"
},
"<5,19,5>": {
"<5,19,5,1>": "QUERY_PARAMS",
"<5,19,5,2>": "first_name,last_name,state"
},
"<5,19,6>": {
"<5,19,6,1>": "TITLE",
"<5,19,6,2>": "Contacts"
}
}
},
"<6>": {
"<6,1>": "3",
"<6,2>": "/contacts/{contactID}",
"<6,3>": "{contactID}",
"<6,4>": {
"<6,4,1>": "Text",
"<6,4,2>": ""
},
"<6,5>": "RESOURCE_ID",
"<6,6>": "",
"<6,7>": {
"<6,7,1>": "RGB{68, 68, 68}",
"<6,7,2>": "White"
},
"<6,8>": {
"<6,8,1>": "Segoe UI",
"<6,8,2>": "-12",
"<6,8,3>": "400",
"<6,8,4>": "0",
"<6,8,5>": "0",
"<6,8,6>": "0",
"<6,8,7>": "1",
"<6,8,8>": "0",
"<6,8,9>": "0",
"<6,8,10>": "0",
"<6,8,11>": "0",
"<6,8,12>": "0"
},
"<6,9>": {
"<6,9,1>": "Left",
"<6,9,2>": "Center"
},
"<6,10>": "N",
"<6,11>": "None",
"<6,12>": "1",
"<6,13>": "24",
"<6,14>": "0",
"<6,15>": "1",
"<6,16>": "None",
"<6,17>": "Left",
"<6,18>": {
"<6,18,1>": "13",
"<6,18,2>": "13"
},
"<6,19>": {
"<6,19,1>": {
"<6,19,1,1>": "DESCRIPTION",
"<6,19,1,2>": "Unique contact ID for the contacts resource."
},
"<6,19,2>": {
"<6,19,2,1>": "API_SIGNATURES",
"<6,19,2,2>": "contacts.ID.PATCH,contacts.ID.PUT,contacts.ID.DELETE,contacts.ID.GET"
},
"<6,19,3>": {
"<6,19,3,1>": "EXCLUDE_LOGGING",
"<6,19,3,2>": "0"
},
"<6,19,4>": {
"<6,19,4,1>": "METHODS",
"<6,19,4,2>": "PATCH,PUT,DELETE,GET"
},
"<6,19,5>": {
"<6,19,5,1>": "QUERY_PARAMS",
"<6,19,5,2>": ""
},
"<6,19,6>": {
"<6,19,6,1>": "TITLE",
"<6,19,6,2>": "Contacts ID"
}
}
},
"<7>": {
"<7,1>": "4",
"<7,2>": "/contacts/{contactID}/picture",
"<7,3>": "picture",
"<7,4>": {
"<7,4,1>": "Text",
"<7,4,2>": ""
},
"<7,5>": "RESOURCE",
"<7,6>": "",
"<7,7>": {
"<7,7,1>": "RGB{68, 68, 68}",
"<7,7,2>": "White"
},
"<7,8>": {
"<7,8,1>": "Segoe UI",
"<7,8,2>": "-12",
"<7,8,3>": "400",
"<7,8,4>": "0",
"<7,8,5>": "0",
"<7,8,6>": "0",
"<7,8,7>": "1",
"<7,8,8>": "0",
"<7,8,9>": "0",
"<7,8,10>": "0",
"<7,8,11>": "0",
"<7,8,12>": "0"
},
"<7,9>": {
"<7,9,1>": "Left",
"<7,9,2>": "Center"
},
"<7,10>": "N",
"<7,11>": "None",
"<7,12>": "1",
"<7,13>": "24",
"<7,14>": "0",
"<7,15>": "1",
"<7,16>": "None",
"<7,17>": "Left",
"<7,18>": {
"<7,18,1>": "13",
"<7,18,2>": "13"
},
"<7,19>": {
"<7,19,1>": {
"<7,19,1,1>": "DESCRIPTION",
"<7,19,1,2>": "Picture resource that is associated with the contact."
},
"<7,19,2>": {
"<7,19,2,1>": "API_SIGNATURES",
"<7,19,2,2>": "picture.PUT,picture.GET"
},
"<7,19,3>": {
"<7,19,3,1>": "EXCLUDE_LOGGING",
"<7,19,3,2>": "0"
},
"<7,19,4>": {
"<7,19,4,1>": "METHODS",
"<7,19,4,2>": "PUT,GET"
},
"<7,19,5>": {
"<7,19,5,1>": "QUERY_PARAMS",
"<7,19,5,2>": ""
},
"<7,19,6>": {
"<7,19,6,1>": "TITLE",
"<7,19,6,2>": "Contacts Picture"
}
}
},
"<8>": {
"<8,1>": "4",
"<8,2>": "/contacts/{contactID}/first_name",
"<8,3>": "first_name",
"<8,4>": {
"<8,4,1>": "Text",
"<8,4,2>": ""
},
"<8,5>": "PROPERTY",
"<8,6>": "",
"<8,7>": {
"<8,7,1>": "RGB{68, 68, 68}",
"<8,7,2>": "White"
},
"<8,8>": {
"<8,8,1>": "Segoe UI",
"<8,8,2>": "-12",
"<8,8,3>": "400",
"<8,8,4>": "0",
"<8,8,5>": "0",
"<8,8,6>": "0",
"<8,8,7>": "1",
"<8,8,8>": "0",
"<8,8,9>": "0",
"<8,8,10>": "0",
"<8,8,11>": "0",
"<8,8,12>": "0"
},
"<8,9>": {
"<8,9,1>": "Left",
"<8,9,2>": "Center"
},
"<8,10>": "N",
"<8,11>": "None",
"<8,12>": "1",
"<8,13>": "24",
"<8,14>": "0",
"<8,15>": "1",
"<8,16>": "None",
"<8,17>": "Left",
"<8,18>": {
"<8,18,1>": "13",
"<8,18,2>": "13"
},
"<8,19>": {
"<8,19,1>": {
"<8,19,1,1>": "DESCRIPTION",
"<8,19,1,2>": "First name property for the contact."
},
"<8,19,2>": {
"<8,19,2,1>": "API_SIGNATURES",
"<8,19,2,2>": "contacts.ID.first_name.GET,contacts.ID.first_name.PUT"
},
"<8,19,3>": {
"<8,19,3,1>": "EXCLUDE_LOGGING",
"<8,19,3,2>": "0"
},
"<8,19,4>": {
"<8,19,4,1>": "METHODS",
"<8,19,4,2>": "GET,PUT"
},
"<8,19,5>": {
"<8,19,5,1>": "QUERY_PARAMS",
"<8,19,5,2>": ""
},
"<8,19,6>": {
"<8,19,6,1>": "TITLE",
"<8,19,6,2>": "Contacts First Name"
}
}
},
"<9>": {
"<9,1>": "4",
"<9,2>": "/contacts/{contactID}/last_name",
"<9,3>": "last_name",
"<9,4>": {
"<9,4,1>": "Text",
"<9,4,2>": ""
},
"<9,5>": "PROPERTY",
"<9,6>": "",
"<9,7>": {
"<9,7,1>": "RGB{68, 68, 68}",
"<9,7,2>": "White"
},
"<9,8>": {
"<9,8,1>": "Segoe UI",
"<9,8,2>": "-12",
"<9,8,3>": "400",
"<9,8,4>": "0",
"<9,8,5>": "0",
"<9,8,6>": "0",
"<9,8,7>": "1",
"<9,8,8>": "0",
"<9,8,9>": "0",
"<9,8,10>": "0",
"<9,8,11>": "0",
"<9,8,12>": "0"
},
"<9,9>": {
"<9,9,1>": "Left",
"<9,9,2>": "Center"
},
"<9,10>": "N",
"<9,11>": "None",
"<9,12>": "1",
"<9,13>": "24",
"<9,14>": "0",
"<9,15>": "1",
"<9,16>": "None",
"<9,17>": "Left",
"<9,18>": {
"<9,18,1>": "13",
"<9,18,2>": "13"
},
"<9,19>": {
"<9,19,1>": {
"<9,19,1,1>": "DESCRIPTION",
"<9,19,1,2>": "Last name property for the contact."
},
"<9,19,2>": {
"<9,19,2,1>": "API_SIGNATURES",
"<9,19,2,2>": "contacts.ID.last_name.GET,contacts.ID.last_name.PUT"
},
"<9,19,3>": {
"<9,19,3,1>": "EXCLUDE_LOGGING",
"<9,19,3,2>": "0"
},
"<9,19,4>": {
"<9,19,4,1>": "METHODS",
"<9,19,4,2>": "GET,PUT"
},
"<9,19,5>": {
"<9,19,5,1>": "QUERY_PARAMS",
"<9,19,5,2>": ""
},
"<9,19,6>": {
"<9,19,6,1>": "TITLE",
"<9,19,6,2>": "Contacts Last Name"
}
}
},
"<10>": {
"<10,1>": "2",
"<10,2>": "/version",
"<10,3>": "version",
"<10,4>": {
"<10,4,1>": "Text",
"<10,4,2>": ""
},
"<10,5>": "RESOURCE",
"<10,6>": "",
"<10,7>": {
"<10,7,1>": "RGB{68, 68, 68}",
"<10,7,2>": "White"
},
"<10,8>": {
"<10,8,1>": "Segoe UI",
"<10,8,2>": "-12",
"<10,8,3>": "400",
"<10,8,4>": "0",
"<10,8,5>": "0",
"<10,8,6>": "0",
"<10,8,7>": "1",
"<10,8,8>": "0",
"<10,8,9>": "0",
"<10,8,10>": "0",
"<10,8,11>": "0",
"<10,8,12>": "0"
},
"<10,9>": {
"<10,9,1>": "Left",
"<10,9,2>": "Center"
},
"<10,10>": "N",
"<10,11>": "None",
"<10,12>": "1",
"<10,13>": "24",
"<10,14>": "0",
"<10,15>": "1",
"<10,16>": "None",
"<10,17>": "Left",
"<10,18>": {
"<10,18,1>": "13",
"<10,18,2>": "13"
},
"<10,19>": {
"<10,19,1>": {
"<10,19,1,1>": "DESCRIPTION",
"<10,19,1,2>": "Service that returns the version of the HTTP Framework."
},
"<10,19,2>": {
"<10,19,2,1>": "API_SIGNATURES",
"<10,19,2,2>": "version.GET"
},
"<10,19,3>": {
"<10,19,3,1>": "METHODS",
"<10,19,3,2>": "GET"
},
"<10,19,4>": {
"<10,19,4,1>": "EXCLUDE_LOGGING",
"<10,19,4,2>": "0"
},
"<10,19,5>": {
"<10,19,5,1>": "QUERY_PARAMS",
"<10,19,5,2>": ""
},
"<10,19,6>": {
"<10,19,6,1>": "TITLE",
"<10,19,6,2>": "API Version"
}
}
},
"<11>": {
"<11,1>": "2",
"<11,2>": "/ping",
"<11,3>": "ping",
"<11,4>": {
"<11,4,1>": "Text",
"<11,4,2>": ""
},
"<11,5>": "RESOURCE",
"<11,6>": "",
"<11,7>": {
"<11,7,1>": "RGB{68, 68, 68}",
"<11,7,2>": "White"
},
"<11,8>": {
"<11,8,1>": "Segoe UI",
"<11,8,2>": "-12",
"<11,8,3>": "400",
"<11,8,4>": "0",
"<11,8,5>": "0",
"<11,8,6>": "0",
"<11,8,7>": "1",
"<11,8,8>": "0",
"<11,8,9>": "0",
"<11,8,10>": "0",
"<11,8,11>": "0",
"<11,8,12>": "0"
},
"<11,9>": {
"<11,9,1>": "Left",
"<11,9,2>": "Center"
},
"<11,10>": "N",
"<11,11>": "None",
"<11,12>": "1",
"<11,13>": "24",
"<11,14>": "0",
"<11,15>": "1",
"<11,16>": "None",
"<11,17>": "Left",
"<11,18>": {
"<11,18,1>": "13",
"<11,18,2>": "13"
},
"<11,19>": {
"<11,19,1>": {
"<11,19,1,1>": "DESCRIPTION",
"<11,19,1,2>": "Used to perform simple ping tests against the API server."
},
"<11,19,2>": {
"<11,19,2,1>": "API_SIGNATURES",
"<11,19,2,2>": "ping.GET"
},
"<11,19,3>": {
"<11,19,3,1>": "METHODS",
"<11,19,3,2>": "GET"
},
"<11,19,4>": {
"<11,19,4,1>": "EXCLUDE_LOGGING",
"<11,19,4,2>": "0"
},
"<11,19,5>": {
"<11,19,5,1>": "QUERY_PARAMS",
"<11,19,5,2>": ""
},
"<11,19,6>": {
"<11,19,6,1>": "TITLE",
"<11,19,6,2>": "Ping Test API"
}
}
},
"<12>": {
"<12,1>": "2",
"<12,2>": "/oauth",
"<12,3>": "oauth",
"<12,4>": {
"<12,4,1>": "Text",
"<12,4,2>": ""
},
"<12,5>": "RESOURCE",
"<12,6>": "",
"<12,7>": {
"<12,7,1>": "RGB{68, 68, 68}",
"<12,7,2>": "White"
},
"<12,8>": {
"<12,8,1>": "Segoe UI",
"<12,8,2>": "-12",
"<12,8,3>": "400",
"<12,8,4>": "0",
"<12,8,5>": "0",
"<12,8,6>": "0",
"<12,8,7>": "1",
"<12,8,8>": "0",
"<12,8,9>": "0",
"<12,8,10>": "0",
"<12,8,11>": "0",
"<12,8,12>": "0"
},
"<12,9>": {
"<12,9,1>": "Left",
"<12,9,2>": "Center"
},
"<12,10>": "N",
"<12,11>": "None",
"<12,12>": "1",
"<12,13>": "24",
"<12,14>": "0",
"<12,15>": "1",
"<12,16>": "None",
"<12,17>": "Left",
"<12,18>": {
"<12,18,1>": "13",
"<12,18,2>": "13"
},
"<12,19>": {
"<12,19,1>": {
"<12,19,1,1>": "DESCRIPTION",
"<12,19,1,2>": "Open Authorization resource API handler."
},
"<12,19,2>": {
"<12,19,2,1>": "API_SIGNATURES",
"<12,19,2,2>": "oauth.GET"
},
"<12,19,3>": {
"<12,19,3,1>": "METHODS",
"<12,19,3,2>": "GET"
},
"<12,19,4>": {
"<12,19,4,1>": "EXCLUDE_LOGGING",
"<12,19,4,2>": "0"
},
"<12,19,5>": {
"<12,19,5,1>": "QUERY_PARAMS",
"<12,19,5,2>": ""
},
"<12,19,6>": {
"<12,19,6,1>": "TITLE",
"<12,19,6,2>": "OpenAuthorization"
}
}
}
}
}
}

View File

@ -0,0 +1,12 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_SERVER_ENABLED"
},
"body": {
"record1": {
"<1>": "1"
}
}
}

View File

@ -0,0 +1,37 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_SETUP"
},
"body": {
"record1": {
"<1>": "127.0.0.1",
"<2>": "/api",
"<3>": "c:\\httpLogs",
"<4>": "1",
"<5>": "Contacts",
"<6>": "HTTP_ENTRY_POINT_SERVICES",
"<7>": "1",
"<8>": {
"<8,1>": "/oauth",
"<8,2>": "/ping"
},
"<9>": "HTTP_ABORTED_SERVICE",
"<10>": "1",
"<11>": "1",
"<12>": "HTTP_DEBUGGER_SERVICE",
"<13>": "0",
"<14>": "",
"<15>": "1",
"<16>": "72",
"<17>": "1",
"<18>": "3",
"<19>": "Quarantine Account",
"<20>": "Web API",
"<21>": "",
"<22>": "",
"<23>": "1"
}
}
}

View File

@ -0,0 +1,31 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_TEMPLATE_API_BODY"
},
"body": {
"record1": {
"<1>": "",
"<2>": "#pragma precomp SRP_PreCompiler",
"<3>": "",
"<4>": "$insert APP_INSERTS",
"<5>": "$insert API_SETUP",
"<6>": "$insert HTTP_INSERTS",
"<7>": "",
"<8>": "GoToAPI else",
"<9>": " // The specific resource endpoint doesn't have a API handler yet.",
"<10>": " HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')",
"<11>": "end",
"<12>": "",
"<13>": "Return Response OR ''",
"<14>": "",
"<15>": "",
"<16>": "////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////",
"<17>": "// Endpoint Handlers",
"<18>": "////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////",
"<19>": "",
"<20>": ""
}
}
}

View File

@ -0,0 +1,47 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_TEMPLATE_API_COMMENT_BLOCK"
},
"body": {
"record1": {
"<1>": "/***********************************************************************************************************************",
"<2>": "",
"<3>": " This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written",
"<4>": " permission from SRP Computer Solutions, Inc.",
"<5>": "",
"<6>": " Name : <Resource>_API",
"<7>": "",
"<8>": " Description : API logic for the <Resource> resource.",
"<9>": "",
"<10>": " Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:",
"<11>": "",
"<12>": " HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)",
"<13>": " APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).",
"<14>": " FullEndpointURL - The URL submitted by the client, including query params.",
"<15>": " FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.",
"<16>": " EndpointSegment - The URL endpoint segment.",
"<17>": " ParentURL - The URL path preceeding the current endpoint.",
"<18>": " CurrentAPI - The name of this stored procedure.",
"<19>": "",
"<20>": " Parameters :",
"<21>": " API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:",
"<22>": " - APIPattern must follow this structure <Resource>[.ID.[<Property>]]",
"<23>": " - HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.",
"<24>": " Examples:",
"<25>": " - <Resource>.POST",
"<26>": " - <Resource>.ID.PUT",
"<27>": " - <Resource>.ID.firstName.GET",
"<28>": " Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API",
"<29>": " services do not rely upon anything being returned in the response. This is what the",
"<30>": " various services like SetResponseBody and SetResponseStatus services are for. A response",
"<31>": " value is only helpful if the developers want to use it for debug purposes.",
"<32>": "",
"<33>": " History : (Date, Initials, Notes)",
"<34>": " MM/DD/YY xxx Original programmer.",
"<35>": "",
"<36>": "***********************************************************************************************************************/"
}
}
}

View File

@ -0,0 +1,12 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_TEMPLATE_API_SIGNATURE"
},
"body": {
"record1": {
"<1>": "Function <Resource>_API(@API)"
}
}
}

View File

@ -0,0 +1,12 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_TOTAL_INVALID_PASSWORD_ATTEMPTS"
},
"body": {
"record1": {
"<1>": "0"
}
}
}

View File

@ -0,0 +1,13 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "SRP_HTTP_FRAMEWORK_VERSION"
},
"body": {
"record1": {
"<1>": "4.0.10.0",
"<2>": "02/08/2022 07:20AM"
}
}
}

View File

@ -0,0 +1,65 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "FRAMEWORKS*SRP_HTTP_FRAMEWORK"
},
"body": {
"record1": {
"<1>": "SRP HTTP Framework",
"<2>": "",
"<3>": "",
"<4>": "",
"<5>": "",
"<6>": "SRP_HTTP_FRAMEWORK",
"<7>": "2",
"<8>": "",
"<9>": "0",
"<10>": "C:\\Users\\dbakk\\Dropbox (SRP)\\SRP Team Folder\\SRP HTTP Framework\\4.0.10\\4.0.10.0\\SRP_HTTP_Framework_4.10.0.0_RDK_64",
"<11>": "",
"<12>": "",
"<13>": "",
"<14>": "",
"<15>": "",
"<16>": "",
"<17>": "",
"<18>": "",
"<19>": "19763",
"<20>": "0",
"<21>": "FRAMEWORKS",
"<22>": "",
"<23>": "",
"<24>": "",
"<25>": "",
"<26>": "",
"<27>": "",
"<28>": "",
"<29>": "",
"<30>": "",
"<31>": "",
"<32>": "",
"<33>": "",
"<34>": "",
"<35>": "",
"<36>": "0",
"<37>": "",
"<38>": "",
"<39>": "",
"<40>": "",
"<41>": "",
"<42>": "",
"<43>": "0",
"<44>": "",
"<45>": "",
"<46>": "",
"<47>": "1",
"<48>": {
"<48,1>": "0",
"<48,2>": "",
"<48,3>": "",
"<48,4>": ""
},
"<49>": "0"
}
}
}

View File

@ -0,0 +1,216 @@
{
"header": {
"version": 1,
"type": "record",
"approw-key": "FRAMEWORKS*SRP_HTTP_FRAMEWORK"
},
"body": {
"record1": {
"<1>": "SRP HTTP FrameWork",
"<2>": "See JIRA Issue SRPFW-82",
"<3>": "",
"<4>": "FRAMEWORKS",
"<5>": "",
"<6>": "",
"<7>": {
"<7,1>": "FRAMEWORKS",
"<7,2>": "FRAMEWORKS",
"<7,3>": "FRAMEWORKS",
"<7,4>": "FRAMEWORKS",
"<7,5>": "FRAMEWORKS",
"<7,6>": "FRAMEWORKS",
"<7,7>": "FRAMEWORKS",
"<7,8>": "FRAMEWORKS",
"<7,9>": "FRAMEWORKS",
"<7,10>": "FRAMEWORKS",
"<7,11>": "FRAMEWORKS",
"<7,12>": "FRAMEWORKS",
"<7,13>": "FRAMEWORKS",
"<7,14>": "FRAMEWORKS",
"<7,15>": "SYSPROG",
"<7,16>": ""
},
"<8>": "",
"<9>": "",
"<10>": "",
"<11>": {
"<11,1>": "Application Rows",
"<11,2>": "3-3:SYSENV:SRP_EDITOR_METADATA_AGENT_API_FRAMEWORKS",
"<11,3>": "3-3:SYSENV:SRP_EDITOR_METADATA_APIROOT_API_FRAMEWORKS",
"<11,4>": "3-3:SYSENV:SRP_EDITOR_METADATA_CONTACTS_API_FRAMEWORKS",
"<11,5>": "3-3:SYSENV:SRP_EDITOR_METADATA_DATABASE_SERVICES_FRAMEWORKS",
"<11,6>": "3-3:SYSENV:SRP_EDITOR_METADATA_ERROR_SERVICES_FRAMEWORKS",
"<11,7>": "3-3:SYSENV:SRP_EDITOR_METADATA_HTTPCLIENT_SERVICES_FRAMEWORKS",
"<11,8>": "3-3:SYSENV:SRP_EDITOR_METADATA_HTTP_AUTHENTICATION_SERVICES_FRAMEWORKS",
"<11,9>": "3-3:SYSENV:SRP_EDITOR_METADATA_HTTP_JSON_SERVICES_FRAMEWORKS",
"<11,10>": "3-3:SYSENV:SRP_EDITOR_METADATA_HTTP_RESOURCE_MANAGER_SERVICES_FRAMEWORKS",
"<11,11>": "3-3:SYSENV:SRP_EDITOR_METADATA_HTTP_RESOURCE_SERVICES_FRAMEWORKS",
"<11,12>": "3-3:SYSENV:SRP_EDITOR_METADATA_HTTP_SERVICES_FRAMEWORKS",
"<11,13>": "3-3:SYSENV:SRP_EDITOR_METADATA_LOGGING_SERVICES_FRAMEWORKS",
"<11,14>": "3-3:SYSENV:SRP_EDITOR_METADATA_MEMORY_SERVICES_FRAMEWORKS",
"<11,15>": "3-3:SYSENV:SRP_EDITOR_METADATA_NDW_WEB_ACCOUNTS_EVENTS_FRAMEWORKS",
"<11,16>": "3-3:SYSENV:SRP_EDITOR_METADATA_OATH_API_FRAMEWORKS",
"<11,17>": "3-3:SYSENV:SRP_EDITOR_METADATA_PICTURE_API_FRAMEWORKS",
"<11,18>": "3-3:SYSENV:SRP_EDITOR_METADATA_PING_API_FRAMEWORKS",
"<11,19>": "3-3:SYSENV:SRP_EDITOR_METADATA_VERSION_API_FRAMEWORKS",
"<11,20>": "3-3:SYSENV:SRP_EDITOR_METADATA_WEBACCOUNTS_API_FRAMEWORKS",
"<11,21>": "3-3:SYSENV:SRP_EDITOR_METADATA_WEBACCOUNTS_SERVICES_FRAMEWORKS",
"<11,22>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_HTTP_LOGS_ARCHIVE_SCRIPT",
"<11,23>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_HTTP_STATUS_CODES",
"<11,24>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_RESOURCES",
"<11,25>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_SERVER_ENABLED",
"<11,26>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_SETUP",
"<11,27>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_TEMPLATE_API_BODY",
"<11,28>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_TEMPLATE_API_COMMENT_BLOCK",
"<11,29>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_TEMPLATE_API_SIGNATURE",
"<11,30>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_TOTAL_INVALID_PASSWORD_ATTEMPTS",
"<11,31>": "3-3:SYSENV:SRP_HTTP_FRAMEWORK_VERSION",
"<11,32>": "3-3:SYSREPOSRELEASES:FRAMEWORKS_SRP_HTTP_FRAMEWORK",
"<11,33>": "3-3:SYSREPOSVIEWS:FRAMEWORKS_SRP_HTTP_FRAMEWORK",
"<11,34>": "Images",
"<11,35>": "2-2:BMP",
"<11,36>": "3-3:SRPHTTPCREATEAPIS",
"<11,37>": "3-3:SRPHTTPDATEFIELD",
"<11,38>": "3-3:SRPHTTPENTRYPOINT",
"<11,39>": "3-3:SRPHTTPINFO",
"<11,40>": "3-3:SRPHTTPPROPERTY",
"<11,41>": "3-3:SRPHTTPREMOVE",
"<11,42>": "3-3:SRPHTTPRENAME",
"<11,43>": "3-3:SRPHTTPRESOURCE",
"<11,44>": "3-3:SRPHTTPRESOURCEID",
"<11,45>": "3-3:SRPHTTPTREECOLLAPSED",
"<11,46>": "3-3:SRPHTTPTREEEXPANDED",
"<11,47>": "3-3:SRPHTTPTREETOPLEVELRESOURCES",
"<11,48>": "2-2:ICO",
"<11,49>": "3-3:SRP",
"<11,50>": "OpenInsight Form Executables",
"<11,51>": "3-3:NDW_HTTP_DATEPICKER",
"<11,52>": "3-3:NDW_HTTP_FRAMEWORK_SETUP",
"<11,53>": "3-3:NDW_HTTP_LOGS",
"<11,54>": "3-3:NDW_HTTP_LOGS_ARCHIVE_DATE",
"<11,55>": "3-3:NDW_WEB_ACCOUNTS",
"<11,56>": "OpenInsight Forms",
"<11,57>": "3-3:NDW_HTTP_DATEPICKER",
"<11,58>": "3-3:NDW_HTTP_FRAMEWORK_SETUP",
"<11,59>": "3-3:NDW_HTTP_LOGS",
"<11,60>": "3-3:NDW_HTTP_LOGS_ARCHIVE_DATE",
"<11,61>": "3-3:NDW_WEB_ACCOUNTS",
"<11,62>": "Popup Boxes",
"<11,63>": "3-3:WEB_ACCOUNTS",
"<11,64>": "Stored Procedure Debug Tables",
"<11,65>": "3-3:APIROOT_API",
"<11,66>": "3-3:CONTACTS_API",
"<11,67>": "3-3:DATABASE_SERVICES",
"<11,68>": "3-3:ERROR_SERVICES",
"<11,69>": "3-3:HTTPCLIENT_SERVICES",
"<11,70>": "3-3:HTTP_ABORTED_SERVICE",
"<11,71>": "3-3:HTTP_AUTHENTICATION_SERVICES",
"<11,72>": "3-3:HTTP_CONTACTS_SERVICES",
"<11,73>": "3-3:HTTP_DEBUGGER_SERVICE",
"<11,74>": "3-3:HTTP_ENTRY_POINT_SERVICES",
"<11,75>": "3-3:HTTP_JSON_SERVICES",
"<11,76>": "3-3:HTTP_MCP",
"<11,77>": "3-3:HTTP_PICTURE_SERVICES",
"<11,78>": "3-3:HTTP_RESOURCE_MANAGER_SERVICES",
"<11,79>": "3-3:HTTP_RESOURCE_SERVICES",
"<11,80>": "3-3:HTTP_SERVICES",
"<11,81>": "3-3:HTTP_VERSION_SERVICES",
"<11,82>": "3-3:HTTP_WEBACCOUNTS_SERVICES",
"<11,83>": "3-3:LOGGING_SERVICES",
"<11,84>": "3-3:MEMORY_SERVICES",
"<11,85>": "3-3:NDW_HTTP_DATEPICKER_EVENTS",
"<11,86>": "3-3:NDW_HTTP_FRAMEWORK_SETUP_EVENTS",
"<11,87>": "3-3:NDW_HTTP_LOGS_ARCHIVE_DATE_EVENTS",
"<11,88>": "3-3:NDW_HTTP_LOGS_EVENTS",
"<11,89>": "3-3:NDW_WEB_ACCOUNTS_EVENTS",
"<11,90>": "3-3:OAUTH_API",
"<11,91>": "3-3:PICTURE_API",
"<11,92>": "3-3:PING_API",
"<11,93>": "3-3:VERSION_API",
"<11,94>": "3-3:WEBACCOUNTS_API",
"<11,95>": "3-3:WEBACCOUNTS_SERVICES",
"<11,96>": "3-3:WEB_ACCOUNTS_ACTIONS",
"<11,97>": "Stored Procedure Executables",
"<11,98>": "3-3:APIROOT_API",
"<11,99>": "3-3:CONTACTS_API",
"<11,100>": "3-3:DATABASE_SERVICES",
"<11,101>": "3-3:ERROR_SERVICES",
"<11,102>": "3-3:HTTPCLIENT_SERVICES",
"<11,103>": "3-3:HTTP_ABORTED_SERVICE",
"<11,104>": "3-3:HTTP_AUTHENTICATION_SERVICES",
"<11,105>": "3-3:HTTP_CONTACTS_SERVICES",
"<11,106>": "3-3:HTTP_DEBUGGER_SERVICE",
"<11,107>": "3-3:HTTP_ENTRY_POINT_SERVICES",
"<11,108>": "3-3:HTTP_JSON_SERVICES",
"<11,109>": "3-3:HTTP_MCP",
"<11,110>": "3-3:HTTP_PICTURE_SERVICES",
"<11,111>": "3-3:HTTP_RESOURCE_MANAGER_SERVICES",
"<11,112>": "3-3:HTTP_RESOURCE_SERVICES",
"<11,113>": "3-3:HTTP_SERVICES",
"<11,114>": "3-3:HTTP_VERSION_SERVICES",
"<11,115>": "3-3:HTTP_WEBACCOUNTS_SERVICES",
"<11,116>": "3-3:LOGGING_SERVICES",
"<11,117>": "3-3:MEMORY_SERVICES",
"<11,118>": "3-3:NDW_HTTP_DATEPICKER_EVENTS",
"<11,119>": "3-3:NDW_HTTP_FRAMEWORK_SETUP_EVENTS",
"<11,120>": "3-3:NDW_HTTP_LOGS_ARCHIVE_DATE_EVENTS",
"<11,121>": "3-3:NDW_HTTP_LOGS_EVENTS",
"<11,122>": "3-3:NDW_WEB_ACCOUNTS_EVENTS",
"<11,123>": "3-3:OAUTH_API",
"<11,124>": "3-3:PICTURE_API",
"<11,125>": "3-3:PING_API",
"<11,126>": "3-3:SRP_PRECOMPILER",
"<11,127>": "3-3:VERSION_API",
"<11,128>": "3-3:WEBACCOUNTS_API",
"<11,129>": "3-3:WEBACCOUNTS_SERVICES",
"<11,130>": "3-3:WEB_ACCOUNTS_ACTIONS",
"<11,131>": "Stored Procedure Inserts",
"<11,132>": "3-3:ACTION_SETUP",
"<11,133>": "3-3:API_SETUP",
"<11,134>": "3-3:APP_INSERTS",
"<11,135>": "3-3:CONTACTS_EQUATES",
"<11,136>": "3-3:HTTP_FRAMEWORK_SETUP_EQUATES",
"<11,137>": "3-3:HTTP_INSERTS",
"<11,138>": "3-3:HTTP_SERVICE_SETUP",
"<11,139>": "3-3:INET_EQUATES",
"<11,140>": "3-3:RTI_LH_INFO_EQUATES",
"<11,141>": "3-3:SERVICE_SETUP",
"<11,142>": "3-3:SRPMAIL_INSERTS",
"<11,143>": "3-3:WEB_ACCOUNTS_EQUATES",
"<11,144>": "Stored Procedures",
"<11,145>": "3-3:APIROOT_API",
"<11,146>": "3-3:CONTACTS_API",
"<11,147>": "3-3:DATABASE_SERVICES",
"<11,148>": "3-3:ERROR_SERVICES",
"<11,149>": "3-3:HTTPCLIENT_SERVICES",
"<11,150>": "3-3:HTTP_ABORTED_SERVICE",
"<11,151>": "3-3:HTTP_AUTHENTICATION_SERVICES",
"<11,152>": "3-3:HTTP_CONTACTS_SERVICES",
"<11,153>": "3-3:HTTP_DEBUGGER_SERVICE",
"<11,154>": "3-3:HTTP_ENTRY_POINT_SERVICES",
"<11,155>": "3-3:HTTP_JSON_SERVICES",
"<11,156>": "3-3:HTTP_MCP",
"<11,157>": "3-3:HTTP_PICTURE_SERVICES",
"<11,158>": "3-3:HTTP_RESOURCE_MANAGER_SERVICES",
"<11,159>": "3-3:HTTP_RESOURCE_SERVICES",
"<11,160>": "3-3:HTTP_SERVICES",
"<11,161>": "3-3:HTTP_VERSION_SERVICES",
"<11,162>": "3-3:HTTP_WEBACCOUNTS_SERVICES",
"<11,163>": "3-3:LOGGING_SERVICES",
"<11,164>": "3-3:MEMORY_SERVICES",
"<11,165>": "3-3:NDW_HTTP_DATEPICKER_EVENTS",
"<11,166>": "3-3:NDW_HTTP_FRAMEWORK_SETUP_EVENTS",
"<11,167>": "3-3:NDW_HTTP_LOGS_ARCHIVE_DATE_EVENTS",
"<11,168>": "3-3:NDW_HTTP_LOGS_EVENTS",
"<11,169>": "3-3:NDW_WEB_ACCOUNTS_EVENTS",
"<11,170>": "3-3:OAUTH_API",
"<11,171>": "3-3:PICTURE_API",
"<11,172>": "3-3:PING_API",
"<11,173>": "3-3:VERSION_API",
"<11,174>": "3-3:WEBACCOUNTS_API",
"<11,175>": "3-3:WEBACCOUNTS_SERVICES",
"<11,176>": "3-3:WEB_ACCOUNTS_ACTIONS"
}
}
}
}

View File

@ -0,0 +1,968 @@
{
"header": {
"version": 1,
"type": "record"
},
"body": {
"record1": {
"<1>": "1010",
"<2>": "7",
"<3>": ""
},
"record2": {
"<1>": {
"<1,1>": "DBW_AUDIT_MANAGER",
"<1,2>": "",
"<1,3>": "WINDOW",
"<1,4>": "",
"<1,5>": "132",
"<1,6>": "269",
"<1,7>": "-571",
"<1,8>": "-360",
"<1,9>": "Audit Manager",
"<1,10>": {
"<1,10,1>": "0x82CF0000",
"<1,10,2>": "0x0"
},
"<1,11>": {
"<1,11,1>": "0x2100",
"<1,11,2>": "0x80000000"
},
"<1,12>": "0",
"<1,13>": "-2",
"<1,14>": "0",
"<1,15>": "",
"<1,16>": "",
"<1,17>": "",
"<1,18>": {
"<1,18,1>": {
"<1,18,1,1>": "R",
"<1,18,1,2>": "EXECUTE",
"<1,18,1,3>": "LSL2*STPROCEXE**DBW_AUDIT_MANAGER_EVENTS",
"<1,18,1,4>": {
"<1,18,1,4,1>": "@SELF",
"<1,18,1,4,2>": "READ"
},
"<1,18,1,5>": "",
"<1,18,1,6>": ""
},
"<1,18,2>": {
"<1,18,2,1>": "R",
"<1,18,2,2>": "EXECUTE",
"<1,18,2,3>": "LSL2*STPROCEXE**DBW_AUDIT_MANAGER_EVENTS",
"<1,18,2,4>": {
"<1,18,2,4,1>": "@SELF",
"<1,18,2,4,2>": "WRITE"
},
"<1,18,2,5>": "",
"<1,18,2,6>": ""
},
"<1,18,3>": ""
},
"<1,19>": {
"<1,19,1>": "READ",
"<1,19,2>": "WRITE",
"<1,19,3>": ""
},
"<1,20>": "",
"<1,21>": "",
"<1,22>": "",
"<1,23>": "APP_INFO",
"<1,24>": {
"<1,24,1>": "0",
"<1,24,2>": "0",
"<1,24,3>": "0",
"<1,24,4>": "0",
"<1,24,5>": "0",
"<1,24,6>": "1"
},
"<1,25>": "0",
"<1,26>": "0",
"<1,27>": "",
"<1,28>": "",
"<1,29>": "",
"<1,30>": "",
"<1,31>": "",
"<1,32>": {
"<1,32,1>": "0x7FFFE",
"<1,32,2>": "0xF001E808"
},
"<1,33>": "",
"<1,34>": "LSL2*IMAGE*ICO*LSL2",
"<1,35>": "",
"<1,36>": "",
"<1,37>": {
"<1,37,1>": "0x20001",
"<1,37,2>": "0x10001"
},
"<1,38>": {
"<1,38,1>": "1",
"<1,38,2>": "1"
},
"<1,39>": "",
"<1,40>": "0",
"<1,41>": "",
"<1,42>": "",
"<1,43>": "",
"<1,44>": "",
"<1,45>": "",
"<1,46>": "",
"<1,47>": "",
"<1,48>": "",
"<1,49>": "",
"<1,50>": "",
"<1,51>": "",
"<1,52>": ""
}
},
"record3": {
"<1>": {
"<1,1>": "EDL_FIELD_TRACEABILITY",
"<1,2>": "",
"<1,3>": "EDITFIELD",
"<1,4>": "DBW_AUDIT_MANAGER",
"<1,5>": "42",
"<1,6>": "16",
"<1,7>": "124",
"<1,8>": "23",
"<1,9>": "AUDIT_MANAGER_SETTINGS",
"<1,10>": {
"<1,10,1>": "0x46000880",
"<1,10,2>": "0x200"
},
"<1,11>": {
"<1,11,1>": "0x4",
"<1,11,2>": "0x80000000"
},
"<1,12>": "1",
"<1,13>": "-2",
"<1,14>": "0",
"<1,15>": {
"<1,15,1>": {
"<1,15,1,1>": "MS Sans Serif",
"<1,15,1,2>": "-11",
"<1,15,1,3>": "400",
"<1,15,1,4>": "0",
"<1,15,1,5>": "0",
"<1,15,1,6>": "0",
"<1,15,1,7>": "0",
"<1,15,1,8>": "34",
"<1,15,1,9>": "0",
"<1,15,1,10>": "1",
"<1,15,1,11>": "2",
"<1,15,1,12>": "1",
"<1,15,1,13>": "0",
"<1,15,1,14>": "0"
}
},
"<1,16>": "",
"<1,17>": "",
"<1,18>": "",
"<1,19>": "",
"<1,20>": "",
"<1,21>": "",
"<1,22>": "",
"<1,23>": "APP_INFO",
"<1,24>": "ID",
"<1,25>": "0",
"<1,26>": "0",
"<1,27>": "",
"<1,28>": "",
"<1,29>": "",
"<1,30>": "",
"<1,31>": "0",
"<1,32>": {
"<1,32,1>": "0x7fffe",
"<1,32,2>": "0xc0016108"
},
"<1,33>": "",
"<1,34>": "",
"<1,35>": "",
"<1,36>": "",
"<1,37>": "",
"<1,38>": "",
"<1,39>": "",
"<1,40>": "",
"<1,41>": "",
"<1,42>": "",
"<1,43>": "",
"<1,44>": "",
"<1,45>": "",
"<1,46>": "",
"<1,47>": "",
"<1,48>": "",
"<1,49>": "",
"<1,50>": "",
"<1,51>": "",
"<1,52>": ""
},
"<2>": {
"<2,1>": "EDT_AUDIT_TABLES",
"<2,2>": "",
"<2,3>": "OLECONTROL.SRP.EditTable.1",
"<2,4>": "DBW_AUDIT_MANAGER",
"<2,5>": "19",
"<2,6>": "20",
"<2,7>": "-20",
"<2,8>": "-21",
"<2,9>": "SRP.EditTable.1",
"<2,10>": {
"<2,10,1>": "0x56000000",
"<2,10,2>": "0x0"
},
"<2,11>": {
"<2,11,1>": "0xC000",
"<2,11,2>": "0x80000000"
},
"<2,12>": "2",
"<2,13>": "-2",
"<2,14>": "0",
"<2,15>": {
"<2,15,1>": {
"<2,15,1,1>": "Tahoma",
"<2,15,1,2>": "-11",
"<2,15,1,3>": "400",
"<2,15,1,4>": "0",
"<2,15,1,5>": "0",
"<2,15,1,6>": "0",
"<2,15,1,7>": "0",
"<2,15,1,8>": "34",
"<2,15,1,9>": "0",
"<2,15,1,10>": "3",
"<2,15,1,11>": "2",
"<2,15,1,12>": "1",
"<2,15,1,13>": "0",
"<2,15,1,14>": "0"
}
},
"<2,16>": "",
"<2,17>": "",
"<2,18>": "",
"<2,19>": "",
"<2,20>": "",
"<2,21>": "",
"<2,22>": "",
"<2,23>": "",
"<2,24>": "",
"<2,25>": "0",
"<2,26>": "0",
"<2,27>": "",
"<2,28>": "<<None>>",
"<2,29>": "<<None>>",
"<2,30>": "<<None>>",
"<2,31>": "0",
"<2,32>": {
"<2,32,1>": "0x7fffe",
"<2,32,2>": "0xf0016400"
},
"<2,33>": "",
"<2,34>": "",
"<2,35>": "",
"<2,36>": "0000000000000000",
"<2,37>": ""
},
"<3>": {
"<3,1>": "OLE_TAB",
"<3,2>": "",
"<3,3>": "OLECONTROL.SRP.Tab.1",
"<3,4>": "DBW_AUDIT_MANAGER",
"<3,5>": "8",
"<3,6>": "7",
"<3,7>": "-8",
"<3,8>": "4",
"<3,9>": "SRP.Tab.1",
"<3,10>": {
"<3,10,1>": "0x56000000",
"<3,10,2>": "0x0"
},
"<3,11>": {
"<3,11,1>": "0x4000",
"<3,11,2>": "0x80000000"
},
"<3,12>": "3",
"<3,13>": "-2",
"<3,14>": "0",
"<3,15>": {
"<3,15,1>": {
"<3,15,1,1>": "Tahoma",
"<3,15,1,2>": "-11",
"<3,15,1,3>": "400",
"<3,15,1,4>": "0",
"<3,15,1,5>": "0",
"<3,15,1,6>": "0",
"<3,15,1,7>": "0",
"<3,15,1,8>": "34",
"<3,15,1,9>": "0",
"<3,15,1,10>": "3",
"<3,15,1,11>": "2",
"<3,15,1,12>": "1",
"<3,15,1,13>": "0",
"<3,15,1,14>": "0"
}
},
"<3,16>": "",
"<3,17>": "",
"<3,18>": "",
"<3,19>": "",
"<3,20>": "",
"<3,21>": "",
"<3,22>": "",
"<3,23>": "",
"<3,24>": "",
"<3,25>": "0",
"<3,26>": "0",
"<3,27>": "",
"<3,28>": "<<None>>",
"<3,29>": "<<None>>",
"<3,30>": "<<None>>",
"<3,31>": "0",
"<3,32>": {
"<3,32,1>": "0x7fffe",
"<3,32,2>": "0xf0016400"
},
"<3,33>": "",
"<3,34>": "",
"<3,35>": "",
"<3,36>": "010000000400000000000000FFFEFF205400610068006F006D006100FCF02D0031003100FCF0340030003000FCF03000FCF03000FCF03000FCF03100FCF03000FCF03000FCF03000FCF03000FCF03000040000000000000001000000000000000100000000000000FFFEFF00FFFEFF044E006F006E00650000000000000000002B020000",
"<3,37>": ""
},
"<4>": {
"<4,1>": "EDT_AUDIT_TBACK",
"<4,2>": "",
"<4,3>": "EDITTABLE",
"<4,4>": "DBW_AUDIT_MANAGER",
"<4,5>": "34",
"<4,6>": "24:1",
"<4,7>": "-66",
"<4,8>": "-303",
"<4,9>": "",
"<4,10>": {
"<4,10,1>": "0x560061D0",
"<4,10,2>": "0x200"
},
"<4,11>": {
"<4,11,1>": "0xC000",
"<4,11,2>": "0x80000002"
},
"<4,12>": "4",
"<4,13>": "-2",
"<4,14>": "0",
"<4,15>": {
"<4,15,1>": {
"<4,15,1,1>": "MS Sans Serif",
"<4,15,1,2>": "-11",
"<4,15,1,3>": "400",
"<4,15,1,4>": "0",
"<4,15,1,5>": "0",
"<4,15,1,6>": "0",
"<4,15,1,7>": "0",
"<4,15,1,8>": "34",
"<4,15,1,9>": "0",
"<4,15,1,10>": "1",
"<4,15,1,11>": "2",
"<4,15,1,12>": "1",
"<4,15,1,13>": "0",
"<4,15,1,14>": "0"
}
},
"<4,16>": "",
"<4,17>": "",
"<4,18>": {
"<4,18,1>": {
"<4,18,1,1>": "R",
"<4,18,1,2>": "EXECUTE",
"<4,18,1,3>": "SYSPROG*STPROCEXE**DBW_AUDIT_MANAGER_EVENTS",
"<4,18,1,4>": {
"<4,18,1,4,1>": "CLICK.EDT_MFS_INFO",
"<4,18,1,4,2>": "@SELF",
"<4,18,1,4,3>": "@PARAM1",
"<4,18,1,4,4>": "@PARAM2",
"<4,18,1,4,5>": "@PARAM3"
},
"<4,18,1,5>": "",
"<4,18,1,6>": ""
},
"<4,18,2>": {
"<4,18,2,1>": "R",
"<4,18,2,2>": "EXECUTE",
"<4,18,2,3>": "SYSPROG*STPROCEXE**DBW_AUDIT_MANAGER_EVENTS",
"<4,18,2,4>": {
"<4,18,2,4,1>": "DBLCLK.EDT_MFS_INFO",
"<4,18,2,4,2>": "@SELF",
"<4,18,2,4,3>": "@PARAM1",
"<4,18,2,4,4>": "@PARAM2",
"<4,18,2,4,5>": "@PARAM3",
"<4,18,2,4,6>": "@PARAM4"
},
"<4,18,2,5>": "",
"<4,18,2,6>": ""
},
"<4,18,3>": {
"<4,18,3,1>": "R",
"<4,18,3,2>": "EXECUTE",
"<4,18,3,3>": "SYSPROG*STPROCEXE**DBW_AUDIT_MANAGER_EVENTS",
"<4,18,3,4>": {
"<4,18,3,4,1>": "GOTFOCUS.EDT_MFS_INFO",
"<4,18,3,4,2>": "@SELF",
"<4,18,3,4,3>": "@PARAM1",
"<4,18,3,4,4>": "@PARAM2",
"<4,18,3,4,5>": "@PARAM3",
"<4,18,3,4,6>": "@PARAM4"
},
"<4,18,3,5>": "",
"<4,18,3,6>": ""
},
"<4,18,4>": {
"<4,18,4,1>": "R",
"<4,18,4,2>": "EXECUTE",
"<4,18,4,3>": "SYSPROG*STPROCEXE**DBW_AUDIT_MANAGER_EVENTS",
"<4,18,4,4>": {
"<4,18,4,4,1>": "OPTIONS.EDT_MFS_INFO",
"<4,18,4,4,2>": "@SELF",
"<4,18,4,4,3>": "@PARAM1"
},
"<4,18,4,5>": "",
"<4,18,4,6>": ""
},
"<4,18,5>": ""
},
"<4,19>": {
"<4,19,1>": "CLICK",
"<4,19,2>": "DBLCLK",
"<4,19,3>": "GOTFOCUS",
"<4,19,4>": "OPTIONS",
"<4,19,5>": ""
},
"<4,20>": "",
"<4,21>": "",
"<4,22>": "",
"<4,23>": {
"<4,23,1>": "APP_INFO",
"<4,23,2>": "APP_INFO",
"<4,23,3>": "APP_INFO",
"<4,23,4>": "APP_INFO",
"<4,23,5>": "APP_INFO",
"<4,23,6>": "APP_INFO",
"<4,23,7>": "APP_INFO"
},
"<4,24>": {
"<4,24,1>": "TABLE_NAME",
"<4,24,2>": "MODIFIED_BY",
"<4,24,3>": "WRITE",
"<4,24,4>": "DELETE",
"<4,24,5>": "READ",
"<4,24,6>": "PROGRAM_TRACKER",
"<4,24,7>": "STATUS"
},
"<4,25>": "0",
"<4,26>": "0",
"<4,27>": "",
"<4,28>": {
"<4,28,1>": "<<Default>>",
"<4,28,2>": "<<Default>>",
"<4,28,3>": "<<Default>>",
"<4,28,4>": "<<Default>>",
"<4,28,5>": "<<Default>>",
"<4,28,6>": "<<Default>>",
"<4,28,7>": "<<Default>>"
},
"<4,29>": {
"<4,29,1>": "<<Default>>",
"<4,29,2>": "<<Default>>",
"<4,29,3>": "<<Default>>",
"<4,29,4>": "<<Default>>",
"<4,29,5>": "<<Default>>",
"<4,29,6>": "<<Default>>",
"<4,29,7>": "<<Default>>"
},
"<4,30>": {
"<4,30,1>": "<<None>>",
"<4,30,2>": "<<None>>",
"<4,30,3>": "<<None>>",
"<4,30,4>": "<<None>>",
"<4,30,5>": "<<None>>",
"<4,30,6>": "<<None>>",
"<4,30,7>": "<<None>>"
},
"<4,31>": {
"<4,31,1>": "0",
"<4,31,2>": "0",
"<4,31,3>": "0",
"<4,31,4>": "0",
"<4,31,5>": "0",
"<4,31,6>": "0",
"<4,31,7>": "0"
},
"<4,32>": {
"<4,32,1>": "0x7e27e",
"<4,32,2>": "0xc0016208"
},
"<4,33>": "",
"<4,34>": "",
"<4,35>": {
"<4,35,1>": "",
"<4,35,2>": ""
},
"<4,36>": "",
"<4,37>": "",
"<4,38>": "",
"<4,39>": {
"<4,39,1>": "80",
"<4,39,2>": "80",
"<4,39,3>": "80",
"<4,39,4>": "80",
"<4,39,5>": "80",
"<4,39,6>": "80",
"<4,39,7>": "80"
},
"<4,40>": "7",
"<4,41>": {
"<4,41,1>": "0",
"<4,41,2>": "",
"<4,41,3>": "",
"<4,41,4>": "",
"<4,41,5>": "",
"<4,41,6>": "",
"<4,41,7>": "",
"<4,41,8>": "40"
},
"<4,42>": {
"<4,42,1>": "16386",
"<4,42,2>": "16384",
"<4,42,3>": "16384",
"<4,42,4>": "16384",
"<4,42,5>": "16384",
"<4,42,6>": "16384",
"<4,42,7>": "16384"
},
"<4,43>": {
"<4,43,1>": "172",
"<4,43,2>": "80",
"<4,43,3>": "80",
"<4,43,4>": "80",
"<4,43,5>": "80",
"<4,43,6>": "80",
"<4,43,7>": "80"
},
"<4,44>": {
"<4,44,1>": "Table",
"<4,44,2>": "Mod. By",
"<4,44,3>": "Write",
"<4,44,4>": "Delete",
"<4,44,5>": "Read",
"<4,44,6>": "Tracker",
"<4,44,7>": "Status"
},
"<4,45>": "",
"<4,46>": "",
"<4,47>": "",
"<4,48>": "",
"<4,49>": "",
"<4,50>": "",
"<4,51>": {
"<4,51,1>": "",
"<4,51,2>": "",
"<4,51,3>": "",
"<4,51,4>": "",
"<4,51,5>": "",
"<4,51,6>": "",
"<4,51,7>": ""
},
"<4,52>": "",
"<4,53>": "",
"<4,54>": "",
"<4,55>": "",
"<4,56>": "",
"<4,57>": "",
"<4,58>": "",
"<4,59>": "",
"<4,60>": {
"<4,60,1>": "2",
"<4,60,2>": "18",
"<4,60,3>": "18",
"<4,60,4>": "18",
"<4,60,5>": "18",
"<4,60,6>": "18",
"<4,60,7>": "18"
}
},
"<5>": {
"<5,1>": "EDT_STOREINFO",
"<5,2>": "",
"<5,3>": "EDITTABLE",
"<5,4>": "DBW_AUDIT_MANAGER",
"<5,5>": "33",
"<5,6>": "91:1",
"<5,7>": "191",
"<5,8>": "45",
"<5,9>": "",
"<5,10>": {
"<5,10,1>": "0x560061D9",
"<5,10,2>": "0x200"
},
"<5,11>": {
"<5,11,1>": "0x60000",
"<5,11,2>": "0x80000000"
},
"<5,12>": "5",
"<5,13>": "-2",
"<5,14>": "0",
"<5,15>": {
"<5,15,1>": {
"<5,15,1,1>": "Tahoma",
"<5,15,1,2>": "-11",
"<5,15,1,3>": "400",
"<5,15,1,4>": "0",
"<5,15,1,5>": "0",
"<5,15,1,6>": "0",
"<5,15,1,7>": "0",
"<5,15,1,8>": "34",
"<5,15,1,9>": "0",
"<5,15,1,10>": "3",
"<5,15,1,11>": "2",
"<5,15,1,12>": "1",
"<5,15,1,13>": "0",
"<5,15,1,14>": "0"
}
},
"<5,16>": "",
"<5,17>": "",
"<5,18>": "",
"<5,19>": "",
"<5,20>": "",
"<5,21>": "",
"<5,22>": "",
"<5,23>": "",
"<5,24>": "",
"<5,25>": "0",
"<5,26>": "0",
"<5,27>": "",
"<5,28>": "<<None>>",
"<5,29>": "<<None>>",
"<5,30>": "<<None>>",
"<5,31>": "0",
"<5,32>": {
"<5,32,1>": "0x7e3fe",
"<5,32,2>": "0xc001ee08"
},
"<5,33>": "",
"<5,34>": "",
"<5,35>": {
"<5,35,1>": "",
"<5,35,2>": ""
},
"<5,36>": "",
"<5,37>": "",
"<5,38>": "",
"<5,39>": "80",
"<5,40>": "1",
"<5,41>": {
"<5,41,1>": "0",
"<5,41,2>": "",
"<5,41,3>": "",
"<5,41,4>": "",
"<5,41,5>": "",
"<5,41,6>": "",
"<5,41,7>": "",
"<5,41,8>": "40"
},
"<5,42>": "16384",
"<5,43>": "150",
"<5,44>": "Stored Tables",
"<5,45>": "",
"<5,46>": "",
"<5,47>": "",
"<5,48>": "",
"<5,49>": "",
"<5,50>": "",
"<5,51>": "",
"<5,52>": "",
"<5,53>": "",
"<5,54>": "",
"<5,55>": "",
"<5,56>": "",
"<5,57>": "",
"<5,58>": "",
"<5,59>": "",
"<5,60>": "18"
},
"<6>": {
"<6,1>": "EDT_MFS_TABLES",
"<6,2>": "",
"<6,3>": "EDITTABLE",
"<6,4>": "DBW_AUDIT_MANAGER",
"<6,5>": "36",
"<6,6>": "153:1",
"<6,7>": "231",
"<6,8>": "33",
"<6,9>": "",
"<6,10>": {
"<6,10,1>": "0x560061D9",
"<6,10,2>": "0x200"
},
"<6,11>": {
"<6,11,1>": "0x60000",
"<6,11,2>": "0x80000000"
},
"<6,12>": "6",
"<6,13>": "-2",
"<6,14>": "0",
"<6,15>": {
"<6,15,1>": {
"<6,15,1,1>": "Tahoma",
"<6,15,1,2>": "-11",
"<6,15,1,3>": "400",
"<6,15,1,4>": "0",
"<6,15,1,5>": "0",
"<6,15,1,6>": "0",
"<6,15,1,7>": "0",
"<6,15,1,8>": "34",
"<6,15,1,9>": "0",
"<6,15,1,10>": "3",
"<6,15,1,11>": "2",
"<6,15,1,12>": "1",
"<6,15,1,13>": "0",
"<6,15,1,14>": "0"
}
},
"<6,16>": "",
"<6,17>": "",
"<6,18>": "",
"<6,19>": "",
"<6,20>": "",
"<6,21>": "",
"<6,22>": "",
"<6,23>": "",
"<6,24>": "",
"<6,25>": "0",
"<6,26>": "0",
"<6,27>": "",
"<6,28>": "<<None>>",
"<6,29>": "<<None>>",
"<6,30>": "<<None>>",
"<6,31>": "0",
"<6,32>": {
"<6,32,1>": "0x7e3fe",
"<6,32,2>": "0xc001ee08"
},
"<6,33>": "",
"<6,34>": "",
"<6,35>": {
"<6,35,1>": "",
"<6,35,2>": ""
},
"<6,36>": "",
"<6,37>": "",
"<6,38>": "",
"<6,39>": "80",
"<6,40>": "1",
"<6,41>": {
"<6,41,1>": "0",
"<6,41,2>": "",
"<6,41,3>": "",
"<6,41,4>": "",
"<6,41,5>": "",
"<6,41,6>": "",
"<6,41,7>": "",
"<6,41,8>": "40"
},
"<6,42>": "16384",
"<6,43>": "191",
"<6,44>": "Attached Tables",
"<6,45>": "",
"<6,46>": "",
"<6,47>": "",
"<6,48>": "",
"<6,49>": "",
"<6,50>": "",
"<6,51>": "",
"<6,52>": "",
"<6,53>": "",
"<6,54>": "",
"<6,55>": "",
"<6,56>": "",
"<6,57>": "",
"<6,58>": "",
"<6,59>": "",
"<6,60>": "18"
},
"<7>": {
"<7,1>": "OLE_SUBCLASS",
"<7,2>": "",
"<7,3>": "OLECONTROL.SRP.Subclass.1",
"<7,4>": "DBW_AUDIT_MANAGER",
"<7,5>": "112",
"<7,6>": "11",
"<7,7>": "83",
"<7,8>": "16",
"<7,9>": "SRP.Subclass.1",
"<7,10>": {
"<7,10,1>": "0x46000000",
"<7,10,2>": "0x0"
},
"<7,11>": {
"<7,11,1>": "0x0",
"<7,11,2>": "0x80000000"
},
"<7,12>": "7",
"<7,13>": "-2",
"<7,14>": "0",
"<7,15>": {
"<7,15,1>": {
"<7,15,1,1>": "Tahoma",
"<7,15,1,2>": "-11",
"<7,15,1,3>": "400",
"<7,15,1,4>": "0",
"<7,15,1,5>": "0",
"<7,15,1,6>": "0",
"<7,15,1,7>": "0",
"<7,15,1,8>": "34",
"<7,15,1,9>": "0",
"<7,15,1,10>": "3",
"<7,15,1,11>": "2",
"<7,15,1,12>": "1",
"<7,15,1,13>": "0",
"<7,15,1,14>": "0"
}
},
"<7,16>": "",
"<7,17>": "",
"<7,18>": "",
"<7,19>": "",
"<7,20>": "",
"<7,21>": "",
"<7,22>": "",
"<7,23>": "",
"<7,24>": "",
"<7,25>": "0",
"<7,26>": "0",
"<7,27>": "",
"<7,28>": "<<None>>",
"<7,29>": "<<None>>",
"<7,30>": "<<None>>",
"<7,31>": "0",
"<7,32>": {
"<7,32,1>": "0x7fffe",
"<7,32,2>": "0xf0016800"
},
"<7,33>": "",
"<7,34>": "",
"<7,35>": "",
"<7,36>": "",
"<7,37>": ""
},
"<8>": ""
},
"record4": {
"<1>": {
"<1,1>": {
"<1,1,1>": "MENU",
"<1,1,2>": "1",
"<1,1,3>": "",
"<1,1,4>": "",
"<1,1,5>": "0",
"<1,1,6>": "0",
"<1,1,7>": "0",
"<1,1,8>": "0",
"<1,1,9>": "5",
"<1,1,10>": "",
"<1,1,11>": "0",
"<1,1,12>": ""
},
"<1,2>": {
"<1,2,1>": "POPUP",
"<1,2,2>": "3",
"<1,2,3>": "",
"<1,2,4>": "&File",
"<1,2,5>": "0",
"<1,2,6>": "0",
"<1,2,7>": "0",
"<1,2,8>": "0",
"<1,2,9>": "",
"<1,2,10>": "",
"<1,2,11>": "0",
"<1,2,12>": ""
},
"<1,3>": {
"<1,3,1>": "ITEM",
"<1,3,2>": "",
"<1,3,3>": "",
"<1,3,4>": "&Save\tCtrl+S",
"<1,3,5>": "0",
"<1,3,6>": "0",
"<1,3,7>": "0",
"<1,3,8>": "595",
"<1,3,9>": "",
"<1,3,10>": "",
"<1,3,11>": "0",
"<1,3,12>": ""
},
"<1,4>": {
"<1,4,1>": "ITEM",
"<1,4,2>": "",
"<1,4,3>": "",
"<1,4,4>": "Save2\tF9",
"<1,4,5>": "0",
"<1,4,6>": "0",
"<1,4,7>": "1",
"<1,4,8>": "120",
"<1,4,9>": "",
"<1,4,10>": "",
"<1,4,11>": "0",
"<1,4,12>": ""
},
"<1,5>": {
"<1,5,1>": "ITEM",
"<1,5,2>": "",
"<1,5,3>": "",
"<1,5,4>": "E&xit",
"<1,5,5>": "0",
"<1,5,6>": "0",
"<1,5,7>": "0",
"<1,5,8>": "0",
"<1,5,9>": "",
"<1,5,10>": "",
"<1,5,11>": "0",
"<1,5,12>": ""
}
},
"<2>": {
"<2,1>": "",
"<2,2>": {
"<2,2,1>": {
"<2,2,1,1>": "E",
"<2,2,1,2>": "WRITE",
"<2,2,1,3>": "@WINDOW",
"<2,2,1,4>": "",
"<2,2,1,5>": "",
"<2,2,1,6>": ""
},
"<2,2,2>": {
"<2,2,2,1>": "E",
"<2,2,2,2>": "WRITE",
"<2,2,2,3>": "@WINDOW",
"<2,2,2,4>": "",
"<2,2,2,5>": "",
"<2,2,2,6>": ""
},
"<2,2,3>": {
"<2,2,3,1>": "E",
"<2,2,3,2>": "CLOSE",
"<2,2,3,3>": "@WINDOW",
"<2,2,3,4>": "",
"<2,2,3,5>": "",
"<2,2,3,6>": ""
},
"<2,2,4>": ""
},
"<2,3>": {
"<2,3,1>": "FILE.SAVE",
"<2,3,2>": "FILE.SAVE2",
"<2,3,3>": "FILE.EXIT",
"<2,3,4>": ""
},
"<2,4>": "0"
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
{
"header": {
"version": 1,
"type": "record"
},
"body": {
"record1": {
"<1>": "1010",
"<2>": "2",
"<3>": ""
},
"record2": {
"<1>": {
"<1,1>": "NDW_HTTP_DATEPICKER",
"<1,2>": "",
"<1,3>": "WINDOW",
"<1,4>": "",
"<1,5>": "474",
"<1,6>": "180",
"<1,7>": "-171",
"<1,8>": "-170",
"<1,9>": "",
"<1,10>": {
"<1,10,1>": "0x82800000",
"<1,10,2>": "0x0"
},
"<1,11>": {
"<1,11,1>": "0x0",
"<1,11,2>": "0x80000000"
},
"<1,12>": "0",
"<1,13>": "-2",
"<1,14>": "0",
"<1,15>": "",
"<1,16>": "",
"<1,17>": "",
"<1,18>": {
"<1,18,1>": {
"<1,18,1,1>": "R",
"<1,18,1,2>": "EXECUTE",
"<1,18,1,3>": "SYSPROG*STPROCEXE**OBJ_CALL_EVENT",
"<1,18,1,4>": {
"<1,18,1,4,1>": "@SELF",
"<1,18,1,4,2>": "@EVENT",
"<1,18,1,4,3>": "@PARAM1",
"<1,18,1,4,4>": "@PARAM2",
"<1,18,1,4,5>": "@PARAM3",
"<1,18,1,4,6>": "@PARAM4",
"<1,18,1,4,7>": "@PARAM5",
"<1,18,1,4,8>": "@PARAM6"
},
"<1,18,1,5>": "",
"<1,18,1,6>": ""
},
"<1,18,2>": {
"<1,18,2,1>": "R",
"<1,18,2,2>": "EXECUTE",
"<1,18,2,3>": "SYSPROG*STPROCEXE**OBJ_CALL_EVENT",
"<1,18,2,4>": {
"<1,18,2,4,1>": "@SELF",
"<1,18,2,4,2>": "@EVENT",
"<1,18,2,4,3>": "@PARAM1",
"<1,18,2,4,4>": "@PARAM2",
"<1,18,2,4,5>": "@PARAM3",
"<1,18,2,4,6>": "@PARAM4",
"<1,18,2,4,7>": "@PARAM5",
"<1,18,2,4,8>": "@PARAM6"
},
"<1,18,2,5>": "",
"<1,18,2,6>": ""
},
"<1,18,3>": ""
},
"<1,19>": {
"<1,19,1>": "CREATE",
"<1,19,2>": "INACTIVATED",
"<1,19,3>": ""
},
"<1,20>": "",
"<1,21>": "",
"<1,22>": "",
"<1,23>": "",
"<1,24>": {
"<1,24,1>": "0",
"<1,24,2>": "0",
"<1,24,3>": "0",
"<1,24,4>": "0",
"<1,24,5>": "0",
"<1,24,6>": "0"
},
"<1,25>": "0",
"<1,26>": "0",
"<1,27>": "",
"<1,28>": "",
"<1,29>": "",
"<1,30>": "",
"<1,31>": "",
"<1,32>": {
"<1,32,1>": "0x7FFFE",
"<1,32,2>": "0xF001E808"
},
"<1,33>": "",
"<1,34>": "FRAMEWORKS*IMAGE*ICO*SRP",
"<1,35>": "",
"<1,36>": "",
"<1,37>": {
"<1,37,1>": "0x10001",
"<1,37,2>": "0x10001"
},
"<1,38>": {
"<1,38,1>": "1",
"<1,38,2>": "1"
},
"<1,39>": "",
"<1,40>": "0",
"<1,41>": "",
"<1,42>": "",
"<1,43>": "",
"<1,44>": "",
"<1,45>": "",
"<1,46>": "",
"<1,47>": "",
"<1,48>": "",
"<1,49>": "",
"<1,50>": "",
"<1,51>": "",
"<1,52>": "",
"<1,53>": "",
"<1,54>": {
"<1,54,1>": "",
"<1,54,2>": "0"
}
}
},
"record3": {
"<1>": {
"<1,1>": "OLE_DATEPICKER",
"<1,2>": "",
"<1,3>": "OLECONTROL.SRP.DatePicker.1",
"<1,4>": "NDW_HTTP_DATEPICKER",
"<1,5>": "0",
"<1,6>": "0",
"<1,7>": "173",
"<1,8>": "173",
"<1,9>": "SRP.DatePicker.1",
"<1,10>": {
"<1,10,1>": "0x56000000",
"<1,10,2>": "0x0"
},
"<1,11>": {
"<1,11,1>": "0xC004",
"<1,11,2>": "0x80000000"
},
"<1,12>": "1",
"<1,13>": "-2",
"<1,14>": "0",
"<1,15>": {
"<1,15,1>": {
"<1,15,1,1>": "Tahoma",
"<1,15,1,2>": "-11",
"<1,15,1,3>": "400",
"<1,15,1,4>": "0",
"<1,15,1,5>": "0",
"<1,15,1,6>": "0",
"<1,15,1,7>": "0",
"<1,15,1,8>": "34",
"<1,15,1,9>": "0",
"<1,15,1,10>": "3",
"<1,15,1,11>": "2",
"<1,15,1,12>": "1",
"<1,15,1,13>": "0",
"<1,15,1,14>": "0"
}
},
"<1,16>": "",
"<1,17>": "",
"<1,18>": {
"<1,18,1>": {
"<1,18,1,1>": "R",
"<1,18,1,2>": "EXECUTE",
"<1,18,1,3>": "SYSPROG*STPROCEXE**OBJ_CALL_EVENT",
"<1,18,1,4>": {
"<1,18,1,4,1>": "@SELF",
"<1,18,1,4,2>": "@EVENT",
"<1,18,1,4,3>": "@PARAM1",
"<1,18,1,4,4>": "@PARAM2",
"<1,18,1,4,5>": "@PARAM3",
"<1,18,1,4,6>": "@PARAM4",
"<1,18,1,4,7>": "@PARAM5",
"<1,18,1,4,8>": "@PARAM6"
},
"<1,18,1,5>": "",
"<1,18,1,6>": ""
},
"<1,18,2>": ""
},
"<1,19>": {
"<1,19,1>": "OLE",
"<1,19,2>": ""
},
"<1,20>": "",
"<1,21>": "",
"<1,22>": "",
"<1,23>": "",
"<1,24>": "",
"<1,25>": "0",
"<1,26>": "0",
"<1,27>": "",
"<1,28>": "<<None>>",
"<1,29>": "<<None>>",
"<1,30>": "<<None>>",
"<1,31>": "0",
"<1,32>": {
"<1,32,1>": "0x7fffe",
"<1,32,2>": "0xf0016400"
},
"<1,33>": "",
"<1,34>": "",
"<1,35>": "",
"<1,36>": "",
"<1,37>": ""
},
"<2>": {
"<2,1>": "PUB_OK",
"<2,2>": "",
"<2,3>": "PUSHBUTTON",
"<2,4>": "NDW_HTTP_DATEPICKER",
"<2,5>": "-102",
"<2,6>": "215",
"<2,7>": "80",
"<2,8>": "18",
"<2,9>": "&OK",
"<2,10>": {
"<2,10,1>": "0x56000000",
"<2,10,2>": "0x0"
},
"<2,11>": {
"<2,11,1>": "0x1109",
"<2,11,2>": "0x80000000"
},
"<2,12>": "2",
"<2,13>": "-2",
"<2,14>": "0",
"<2,15>": {
"<2,15,1>": {
"<2,15,1,1>": "MS Sans Serif",
"<2,15,1,2>": "-11",
"<2,15,1,3>": "400",
"<2,15,1,4>": "0",
"<2,15,1,5>": "0",
"<2,15,1,6>": "0",
"<2,15,1,7>": "0",
"<2,15,1,8>": "34",
"<2,15,1,9>": "0",
"<2,15,1,10>": "1",
"<2,15,1,11>": "2",
"<2,15,1,12>": "1",
"<2,15,1,13>": "0",
"<2,15,1,14>": "0"
}
},
"<2,16>": "",
"<2,17>": "",
"<2,18>": {
"<2,18,1>": {
"<2,18,1,1>": "R",
"<2,18,1,2>": "EXECUTE",
"<2,18,1,3>": "SYSPROG*STPROCEXE**OBJ_CALL_EVENT",
"<2,18,1,4>": {
"<2,18,1,4,1>": "@SELF",
"<2,18,1,4,2>": "@EVENT",
"<2,18,1,4,3>": "@PARAM1",
"<2,18,1,4,4>": "@PARAM2",
"<2,18,1,4,5>": "@PARAM3",
"<2,18,1,4,6>": "@PARAM4",
"<2,18,1,4,7>": "@PARAM5",
"<2,18,1,4,8>": "@PARAM6"
},
"<2,18,1,5>": "",
"<2,18,1,6>": ""
},
"<2,18,2>": ""
},
"<2,19>": {
"<2,19,1>": "CLICK",
"<2,19,2>": ""
},
"<2,20>": "",
"<2,21>": "",
"<2,22>": "",
"<2,23>": "",
"<2,24>": "",
"<2,25>": "0",
"<2,26>": "0",
"<2,27>": "",
"<2,28>": "<<None>>",
"<2,29>": "<<None>>",
"<2,30>": "<<None>>",
"<2,31>": "0",
"<2,32>": {
"<2,32,1>": "0x7fffe",
"<2,32,2>": "0xf0016088"
},
"<2,33>": "",
"<2,34>": "",
"<2,35>": "",
"<2,36>": "",
"<2,37>": "",
"<2,38>": "",
"<2,39>": "",
"<2,40>": "1",
"<2,41>": "",
"<2,42>": "",
"<2,43>": "",
"<2,44>": "",
"<2,45>": "",
"<2,46>": "",
"<2,47>": "",
"<2,48>": "",
"<2,49>": "",
"<2,50>": "",
"<2,51>": ""
},
"<3>": ""
},
"record4": {
"<1>": {
"<1,1>": {
"<1,1,1>": "MENU",
"<1,1,2>": "1",
"<1,1,3>": "",
"<1,1,4>": "",
"<1,1,5>": "0",
"<1,1,6>": "0",
"<1,1,7>": "0",
"<1,1,8>": "0",
"<1,1,9>": "2",
"<1,1,10>": "",
"<1,1,11>": "0",
"<1,1,12>": ""
},
"<1,2>": {
"<1,2,1>": "ITEM",
"<1,2,2>": "",
"<1,2,3>": "",
"<1,2,4>": "Close window\tEsc",
"<1,2,5>": "0",
"<1,2,6>": "0",
"<1,2,7>": "1",
"<1,2,8>": "27",
"<1,2,9>": "",
"<1,2,10>": "",
"<1,2,11>": "0",
"<1,2,12>": ""
}
},
"<2>": {
"<2,1>": "",
"<2,2>": {
"<2,2,1>": {
"<2,2,1,1>": "E",
"<2,2,1,2>": "CLOSE",
"<2,2,1,3>": "@WINDOW",
"<2,2,1,4>": "",
"<2,2,1,5>": "",
"<2,2,1,6>": ""
},
"<2,2,2>": ""
},
"<2,3>": {
"<2,3,1>": "CLOSE_WINDOW",
"<2,3,2>": ""
},
"<2,4>": "0"
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
{
"header": {
"version": 1,
"type": "record"
},
"body": {
"record1": {
"<1>": "-1",
"<2>": "-1",
"<3>": "-1",
"<4>": "-1",
"<5>": "16777215",
"<6>": {
"<6,1>": {
"<6,1,1>": "Segoe UI",
"<6,1,2>": "-12",
"<6,1,3>": "400",
"<6,1,4>": "0",
"<6,1,5>": "0",
"<6,1,6>": "0",
"<6,1,7>": "0",
"<6,1,8>": "34",
"<6,1,9>": "0",
"<6,1,10>": "3",
"<6,1,11>": "2",
"<6,1,12>": "1",
"<6,1,13>": "11",
"<6,1,14>": "2",
"<6,1,15>": "0",
"<6,1,16>": "0"
}
},
"<7>": "WEB_ACCOUNTS",
"<8>": "BY NAME BY @ID",
"<9>": {
"<9,1>": {
"<9,1,1>": "ID",
"<9,1,2>": "10",
"<9,1,3>": "L",
"<9,1,4>": "C",
"<9,1,5>": "",
"<9,1,6>": "ID"
},
"<9,2>": {
"<9,2,1>": "NAME",
"<9,2,2>": "20",
"<9,2,3>": "L",
"<9,2,4>": "C",
"<9,2,5>": "",
"<9,2,6>": "Name"
},
"<9,3>": {
"<9,3,1>": "ACCOUNT_ENABLED",
"<9,3,2>": "10",
"<9,3,3>": "L",
"<9,3,4>": "C",
"<9,3,5>": "B",
"<9,3,6>": "Enabled"
}
},
"<10>": "T",
"<11>": "1",
"<12>": "Web Accounts",
"<13>": "1",
"<14>": "F",
"<15>": "1",
"<16>": "1",
"<17>": "1",
"<18>": "1",
"<19>": "1",
"<20>": "1",
"<21>": "1",
"<22>": "0",
"<23>": "0",
"<24>": "0",
"<25>": "0",
"<26>": "",
"<27>": "",
"<28>": "",
"<29>": "0",
"<30>": "0",
"<31>": "0",
"<32>": "1",
"<33>": "0",
"<34>": "-2",
"<35>": "-2",
"<36>": "",
"<37>": "",
"<38>": "",
"<39>": "",
"<40>": "-2",
"<41>": "1000",
"<42>": "",
"<43>": "",
"<44>": "",
"<45>": ""
}
}
}

View File

@ -0,0 +1,100 @@
Function APIRoot_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : APIRoot_API
Description : API logic for the Apiroot resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client, including query params.
FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.
ParentURL - The URL path preceeding the current endpoint.
the SelfURL.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
- APIPattern must follow this structure <Resource>[.ID.[<Property>]]
- HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
Examples:
- APIROOT.POST
- APIROOT.ID.PUT
- APIROOT.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
11/19/18 dmb Original programmer.
04/09/19 dmb [SRPFW-271] Update the APIROOT.GET API to verify that the AuthenticatedAccountID has a value
before adding the resetPassword form action.
04/29/19 dmb Update the APIROOT.GET API to verify the sub-resource has at least one HTTP method before
adding it.
05/28/19 dmb [SRPFW-274] Replace all references to AddLinkRelationship with AddLinkRelation.
07/16/19 dmb [SRPFW-277] Retrofit APIROOT.GET API to use the HTTP_Resource_Manager_Services module.
01/23/20 dmb [SRPFW-296] Add matching HEAD APIs for all GET APIs.
01/26/20 dmb [SRPFW-296] Update the APIROOT.GET API so link relations are templated whenever possible.
02/13/20 dmb [SRPFW-311] Fix a minor typo in the APIROOT.GET API.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
$insert HTTP_FRAMEWORK_SETUP_EQUATES
Declare function Database_Services, HTTP_Resource_Manager_Services
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API APIROOT.HEAD
API APIROOT.GET
objResource = HTTP_Resource_Services('GetObject')
If Error_Services('NoError') then
HTTP_Resource_Services('AddLinkRelation', objResource, 'self', FullEndpointURL)
RootResources = HTTP_Resource_Manager_Services('GetResourceChildren', FullEndpointURL, 'RESOURCE')
For Each Resource in RootResources using @FM
Methods = HTTP_Resource_Manager_Services('GetResourceProperty', Resource, 'METHODS')
If Methods NE '' then
Name = HTTP_Resource_Manager_Services('GetResourceProperty', Resource, 'NAME')
Title = HTTP_Resource_Manager_Services('GetResourceProperty', Resource, 'TITLE')
HTTP_Resource_Services('AddLinkRelation', objResource, Name, FullEndpointURL : '/' : Resource[-1, 'B/'], Title, True$)
end
Next Resource
end
If Error_Services('NoError') then
AuthenticatedAccountID = HTTP_Authentication_Services('GetAuthenticatedAccountID')
If AuthenticatedAccountID NE '' then
HTTP_Resource_Services('AddFormAction', objResource, 'resetPassword', 'PATCH', FullEndpointURL : '/webaccounts/' : AuthenticatedAccountID : '/password', 'Reset Password', 'value', '' : @VM : True$ : @VM : True$)
end
end
If Error_Services('NoError') then
Services = HTTP_Resource_Services('GetSerializedResource', objResource)
HTTP_Services('SetResponseBody', Services, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end api

View File

@ -0,0 +1,210 @@
Subroutine Audit_Manager(ID, Table, CurrentRecord, OrigRecord, Activity)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Audit_Manager
Description : Updates the Audit table to track modifications of a record.
Notes : This process is normally called by the Audit_Manager_MFS. It handles all of the audit trail
management logic.
Parameters :
AutoSet [in] -- Allows automatic setting of the SYSTEM_MAINTENANCE record without user intervention.
SysFlag [out] -- Returns True if the flag was set to stop people from logging in. Returns False if people
are still allowed to log into the application.
ID [in] -- ID of the record.
Table [in] -- Table name where the record being audited is stored.
CurrentRecord [in/out] -- Current record as it will be written to disk. If the Activity is "Write" then the
audit fields will be updated.
OrigRecord [in] -- If called by Audit_Manager_MFS then this is the original record, otherwise this
represents a marker for special audit tracking.
Activity [in] -- Identifies the audit activity being performed: Read, Write, Delete, or anything else
if called directly for special audit tracking.
History : (Date, Initials, Notes)
05/19/05 axf Initial Program (Original Program MFS_Update_History).
11/26/07 dmb Code clean-up and refactoring.
04/05/13 dmb Repalce SECURITY_EQUATES with Memory Services to get login security. - [SRPFW-9]
***********************************************************************************************************************/
$insert APP_INSERTS
Declare Subroutine Msg, Lock_Record
Declare Function RetStack, Memory_Services
If Assigned(ID) else ID = ""
If Assigned(Table) else Table = ""
If Assigned(CurrentRecord) else CurrentRecord = ""
If Assigned(OrigRecord) else OrigRecord = ""
AuditManagerTable = "APP_INFO"
Convert @Lower_Case to @Upper_Case In Table
AuditTable = 'AUDIT_' : Table
Username = @USERNAME
* Declare function GetNetworkUsername
* If GetNetworkUsername() EQ "dbakke1" AND Activity _NEC "READ" then debug
Open AuditTable to HistoryCheck then
RecordTracker = No$
Locked_handle = ""
Temp_activity = ""
Success = ""
Details = ""
New = No$
TrackActivity = No$
CallProgName = RetStack()<2>
Gosub App_Info
If TrackActivity EQ Yes$ then Gosub Main_Process
End
Return
App_Info:
Fields = ""
Num_fields = 0
Open AuditManagerTable to hAIT then
ReadO App_record from hAIT, "AUDIT_MANAGER_SETTINGS" then
Locate Table in App_record<1> using @VM setting vPos then
Begin Case
Case ID EQ ""
// Do nothing.
Case CallProgName[1, 18] NE "AUDIT_MANAGER_MFS*"
// Program is being called directly from a stored procedure.
If App_record<6,vPos> EQ Yes$ Then
If CurrentRecord NE "" Then
TrackActivity = Yes$
RecordTracker = Yes$ ; // Flag to indicate that special audit tracking is ocurring
Marker = OrigRecord
OrigRecord = CurrentRecord
End
End
Case Activity EQ "Write"
If App_record<3,vPos> EQ Yes$ Then
TrackActivity = Yes$
Locate Table in App_record<1> using @VM setting Position then
StartField = App_record<2, Position>
If StartField Then
CurrentRecord<StartField> = Username
CurrentRecord<StartField + 1> = Date()
CurrentRecord<StartField + 2> = Time()
End
End
End
Case Activity EQ "Delete"
If App_record<4,vPos> EQ Yes$ Then TrackActivity = Yes$
Case Activity EQ "Read"
If App_record<5,vPos> EQ Yes$ Then TrackActivity = Yes$
End Case
end else
* Msg("|Unable to locate the ":Table:" information|in the Audit Manager Settings.|")
end
end else
* Msg("|Unable to read the Audit Manager Settings Record.|")
end
end else
* Msg("|Unable to open the App_Info Table.|")
end
return
Main_Process:
Lock_Record(AuditTable, Locked_handle, ID, Lock$, No$, Yes$, Success)
If Success then
Read AuditTrail from Locked_handle, ID then
Num_items = Count(AuditTrail<1>, @VM) + (AuditTrail<1> NE "")
* If Len(AuditTrail) GT 250000 then
* For DelNumItems = 1 to 100
* For Loop = 1 to 8
* AuditTrail = Delete(AuditTrail, Loop, Num_items, 0)
* Next Loop
* Num_items -= 1
* Next DelNumItems
* end
end else
AuditTrail = ""
New = Yes$
end
Current_date = Date()
Current_time = Time()
Seq = "DR"
StationName = @Station
MacAddress = ""
Locate Current_date in AuditTrail<1> by Seq Using @VM setting Pos else Null
AuditTrail<1> = Insert(AuditTrail<1>, 1, Pos, 0, Current_Date)
AuditTrail<2> = Insert(AuditTrail<2>, 1, Pos, 0, Current_Time)
AuditTrail<3> = Insert(AuditTrail<3>, 1, Pos, 0, Username)
AuditTrail<4> = Insert(AuditTrail<4>, 1, Pos, 0, StationName)
AuditTrail<5> = Insert(AuditTrail<5>, 1, Pos, 0, MacAddress)
AuditTrail<8> = Insert(AuditTrail<8>, 1, Pos, 0, Activity)
AuditTrail<9> = "AUDIT TRACKING RECORD"
If RecordTracker EQ Yes$ Then
// Special audit tracking is occuring. Store the current program
// and the special marker in the audit trail entry.
AuditTrail<6> = Insert(AuditTrail<6>, 1, Pos, 0, RetStack()<2>)
AuditTrail<7> = Insert(AuditTrail<7>, 1, Pos, 0, Marker)
AuditTrail<10> = "PROGRAM TRACKER"
End Else
AuditTrail<6> = Insert(AuditTrail<6>, 1, Pos, 0, "")
AuditTrail<7> = Insert(AuditTrail<7>, 1, Pos, 0, "")
AuditTrail<10> = AuditTrail<10>
End
// Update the Audit Trail record.
Write AuditTrail to Locked_handle, ID Then
If Activity NE "Read" Then
// Only create an audit record if the Activity isn't Read.
AuditRecord = OrigRecord
If MacAddress EQ "" Then MacAddress = @Station
StoredRecId = ID:"*":MacAddress:"*":Current_Date:"*":Current_Time
Write AuditRecord To Locked_handle, StoredRecId Then
Read RecentlyUpdatedList from Locked_handle, "%RECENTLY_UPDATED%" Else
RecentlyUpdatedList = ""
End
Locate ID in RecentlyUpdatedList using @FM setting UpdatePos Then
RecentlyUpdatedList = Delete(RecentlyUpdatedList, UpdatePos, 0, 0)
End
If RecentlyUpdatedList EQ "" then
RecentlyUpdatedList = ID
End Else
RecentlyUpdatedList = ID:@FM:RecentlyUpdatedList
If Count(RecentlyUpdatedList, @FM) GT 499 then
RecentlyUpdatedList = Field(RecentlyUpdatedList, @FM, 1, 500)
end
End
Write RecentlyUpdatedList to Locked_handle, "%RECENTLY_UPDATED%" Else
* Msg("|Unable to Write the record %RECENTLY_UPDATED%|to the ":AuditTable:".|")
End
End Else
* Msg("|Unable to Write the record ":StoredRecId:"|to the ":AuditTable:".|")
End
End
End Else
* Msg("|Unable to Write the record ":ID:"|to the ":AuditTable:".|")
End
Lock_Record(AuditTable, Locked_handle, ID, Unlock$)
End Else
* Msg("|Unable to update ":AuditTable:" log.|")
end
return

View File

@ -0,0 +1,265 @@
Function Audit_Manager_MFS(Code, BFS, Handle, Name, FMC, Record, Status)
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
//
// This program is proprietary and is not to be used by or disclosed to others, nor is it to
// be copied without written permission from SRP Computer Solutions, Inc.
//
// Name : Audit_Manager_MFS
//
// Description: MFS for tracking the audit history of a particular record.
//
// Notes: This routine primarily passes all essential information into the Audit_Manager
// stored procedure. This way changes to the core functionality can be made
// without having to restart OpenInsight (which is necessary for changes directly
// in MFS procedures.)
//
// A check is first made to see if corresponding audit table exists for the
// database table that triggered this MFS. Audit tables use a naming convention
// of AUDIT_Tablename. therefore, if the CUSTOMERS table is being audited then
// there should be an AUDIT_CUSTOMERS table available. Audit features are managed
// by the DBW_AUDIT_MANAGER form.
//
// Parameters:
// Code [in] -- An integer value indicating the operation to be performed (1 = read a
// record, 4 = delete a record, 11 = open a file, etc.)
// BFS [in] -- The list of MFSs and the BFS name for the current file or volume. This
// is a subvalue mark-delimited array, with the current MFS name as the
// first value in the array, and the BFS name as the last value.
// Handle [in] -- The file handle of the file or media map being accessed.
// Name [in] -- The name (key) of the record or file being accessed.
// FMC [in] -- Various functions.
// Record [in] -- The entire record (for record-oriented functions) or a newly-created
// handle (for "get handle" functions).
// Status [in] -- A return code indicating the success or failure of an operation.
//
// History (Date, Initials, Notes)
// 01/04/00 pcs Original programmer
// 01/20/00 pcs CLEARFILE requires the Arev table name to be removed before processing
// 05/20/05 axf Process will now also track the accessing of records.
// 11/26/07 dmb Code clean-up. No functional changes were made.
//
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
$insert APP_INSERTS
$INSERT FILE.SYSTEM.EQUATES
$INSERT FSERRORS_HDR
Declare Subroutine Msg, Audit_Manager
ON CODE GOSUB READ.RECORD,READO.RECORD,WRITE.RECORD,DELETE.RECORD,LOCK.RECORD,UNLOCK.RECORD,SELECT,READNEXT,CLEARSELECT,CLEARFILE,OPEN.FILE,CREATE.FILE,RENAME.FILE,MOVE.FILE,DELETE.FILE,OPEN.MEDIA,CREATE.MEDIA,READ.MEDIA,WRITE.MEDIA,UNLOCK.ALL,FLUSH,INSTALL,RESERVED,RESERVED,RESERVED,OMNI.SCRIPT,CLOSE.MEDIA,RECORD.COUNT, REMAKE.FILE,CREATE.INDEX,DELETE.INDEX,UPDATE.INDEX,SELECT.INDEX,READNEXT.INDEX
Return
READ.RECORD:
// Added Check_Update_History Gosub
Activity = "Read"
GoSub Check_Update_History
GoSub Remove_Arev_Table_Name
return
READO.RECORD:
// Added Check_Update_History Gosub
Activity = "Read"
GoSub Check_Update_History
GoSub Remove_Arev_Table_Name
return
CREATE.MEDIA:
GoSub Call_NextFS
return
OPEN.MEDIA:
GoSub Call_NextFS
return
READ.MEDIA:
GoSub Call_NextFS
return
WRITE.MEDIA:
GoSub Call_NextFS
return
CLOSE.MEDIA:
GoSub Call_NextFS
return
CLEARFILE:
GoSub Remove_Arev_Table_Name
return
CREATE.FILE:
GoSub Call_NextFS
return
DELETE.FILE:
GoSub Call_NextFS
return
MOVE.FILE:
GoSub Call_NextFS
return
OPEN.FILE:
// Attaching Arev Table name to Handle for checking purposes
GoSub Call_NextFS
If Index(RECORD, @TM, 1) EQ 0 then
RECORD = NAME:@TM:RECORD
end
return
REMAKE.FILE:
GoSub Call_NextFS
return
RENAME.FILE:
GoSub Call_NextFS
return
SELECT:
GoSub Remove_Arev_Table_Name
return
READNEXT:
GoSub Remove_Arev_Table_Name
return
CLEARSELECT:
GoSub Remove_Arev_Table_Name
return
LOCK.RECORD:
GoSub Remove_Arev_Table_Name
return
UNLOCK.RECORD:
GoSub Remove_Arev_Table_Name
return
CREATE.INDEX:
GoSub Remove_Arev_Table_Name
return
UPDATE.INDEX:
GoSub Remove_Arev_Table_Name
return
DELETE.INDEX:
GoSub Remove_Arev_Table_Name
return
SELECT.INDEX:
GoSub Remove_Arev_Table_Name
return
READNEXT.INDEX:
GoSub Remove_Arev_Table_Name
return
RESERVED:
GoSub Call_NextFS
return
OMNI.SCRIPT:
GoSub Remove_Arev_Table_Name
return
RECORD.COUNT:
GoSub Remove_Arev_Table_Name
return
LOCK.SEMAPHORE:
GoSub Call_NextFS
return
UNLOCK.SEMAPHORE:
GoSub Call_NextFS
return
SET.USER.SEMAPHORE:
GoSub Call_NextFS
return
WRITE.RECORD:
GoSub Prep_Vars
Activity = "Write"
GoSub Check_Update_History
GoSub Remove_Arev_Table_Name
return
DELETE.RECORD:
Activity = "Delete"
GoSub Check_Update_History
GoSub Remove_Arev_Table_Name
return
NEXT_FS:
GoSub Call_NextFS
return
// Install, unlock all and flush are called directly, no need to call next FS.
INSTALL:
STATUS = TRUE$
return
FLUSH:
STATUS = TRUE$
return
UNLOCK.ALL:
STATUS = TRUE$
return
Prep_Vars:
TempUseTable = Field(HANDLE, @TM, 1)
UseTable = Field(TempUseTable, "*", 1)
UseID = Name
return
Check_Update_History:
Temp_File_Name = Field(HANDLE, @TM, 1)
FileName = Field(Temp_File_Name, "*", 1)
Real_Handle = Field(HANDLE, @TM, 2)
History_table = "AUDIT_":FileName
Open History_table to HistoryCheck then
GoSub Get_Original_Record
Audit_Manager(Name, FileName, Record, OrigRecord, Activity)
end
return
Get_Original_Record:
OrigRecord = ""
CALL RTP57(READO.RECORD, "RTP57", Real_Handle, NAME, FMC, OrigRecord, Temp_status)
// If Temp_status is Null then it is a new record or an error reading.
return
Call_NextFS:
FS = DELETE(BFS, 1, 1, 1)
NEXTFS = FS<1, 1, 1>
@FILE.ERROR = ""
CALL @NEXTFS(CODE, FS, HANDLE, NAME, FMC, RECORD, STATUS)
return
Remove_Arev_Table_Name:
* FileName = Field(HANDLE, @TM, 1)
* If FileName EQ HANDLE then
* Real_Handle = HANDLE
* end else
* Real_Handle = Field(HANDLE, @TM, 2)
* end
FS = DELETE(BFS, 1, 1, 1)
NEXTFS = FS<1, 1, 1>
@FILE.ERROR = ""
If Index(FS, @SVM, 1) GT 0 then
Real_Handle = HANDLE
end else
Real_Handle = Field(HANDLE, @TM, 2)
end
CALL @NEXTFS(CODE, FS, Real_Handle, NAME, FMC, RECORD, STATUS)
return

View File

@ -0,0 +1,284 @@
Function Contacts_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Contacts_API
Description : API logic for the Contacts resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client, including query params.
FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.
ParentURL - The URL path preceeding the current endpoint.
the SelfURL.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
- APIPattern must follow this structure <Resource>[.ID.[<Property>]]
- HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
Examples:
- Contacts.POST
- Contacts.ID.PUT
- Contacts.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
11/17/18 dmb Original programmer.
04/09/19 dmb [SRPFW-271] Replace FullEndpointURL with FullEndpointURLNoQuery in the GetObjects service
within the Contacts.GET API to avoid query params in the embedded object self URLs.
05/28/19 dmb [SRPFW-274] Replace all references to AddLinkRelationships with AddLinkRelations.
05/31/19 dmb [SRPFW-276] Update contacts.ID.GET API by removing unnecessary call to the GetDatabaseItem
service.
01/23/20 dmb [SRPFW-296] Add matching HEAD APIs for all GET APIs.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
$insert CONTACTS_EQUATES
Declare function Database_Services
Declare subroutine RList
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API contacts.HEAD
API contacts.GET
DisplayColumnNames = 'first_name' : @FM : 'last_name' : @FM : 'email'
If HTTP_Services('GetHTTPGetString') NE '' then
// This means the URL ends with /contacts?{property}={value}. The client is searching for one or more contacts
// that match the query parameters. This is equivalent to doing a filtered RLIST search.
// Get the query string passed into the URL.
GetString = HTTP_Services('GetHTTPGetString')
// Get the name of the property being queried.
Property = GetString[1, 'F=']
// Get the value being searched for.
Value = HTTP_Services('GetQueryField', Property)
// Get the database columns for the table.
ColumnNames = HTTP_Resource_Services('GetColumnNames', 'CONTACTS')
ColumnName = Property
Convert @Lower_Case to @Upper_Case in ColumnName
// Verify the property matches a valid column in the table.
Locate ColumnName in ColumnNames using @FM setting fPos then
// Use the GetDatabaseItems service to perform the search and prepare the HAL+JSON response. If a more complex
// or optimized solution is needed, then replace the following with custom code.
Filter = 'SELECT CONTACTS WITH ' : ColumnName : ' CONTAINING ' : Quote(Value)
// The GetDatabaseItems service will return all database column values unless otherwise specified. Since a query
// search might generated several results, it is sometimes best to pass in just those columns that are important
// for the query result.
Locate ColumnName in DisplayColumnNames using @FM setting fPos else
// Make sure the property being searched is included in the columns being returned.
DisplayColumnNames := @FM : Property
end
end else
// This is not a valid property, which means the URL does not resolve. Set a 404 error. Add a description if
// desired.
Error_Services('Add', ColumnName : ' is not a valid column in the CONTACTS table.')
HTTP_Services('SetResponseError', '', '', 404, Error_Services('GetMessage'), FullEndpointURL)
end
end else
// This means the URL ends with /contacts. The client is requesting all resources available at this URL.
// This is equivalent to performing an unfiltered SELECT statement. Pass in an empty filter.
Filter = ''
end
If Error_Services('NoError') then
objResource = HTTP_Resource_Services('GetObject')
If Error_Services('NoError') then
objContacts = HTTP_Resource_Services('GetObjects', 'CONTACTS', Filter, DisplayColumnNames, '', '', '', '', FullEndpointURLNoQuery)
HTTP_Resource_Services('AddEmbeddedResources', objResource, 'contacts', objContacts)
// Add _links sub-properties for HAL implementation.
Rels = 'self' : @FM : 'apiEntryPoint'
URLs = FullEndpointURL : @FM : ParentURL
HTTP_Resource_Services('AddLinkRelations', objResource, Rels, URLs)
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end
end api
API contacts.POST
* HTTP_Resource_Services('PostDatabaseItem', 'CONTACTS', FullEndpointURL)
* Call Push.Session(Hold1, Hold2, Hold3, Hold4, Hold5, Hold6)
* Call Pop.Session(Hold1, Hold2, Hold3, Hold4, Hold5, Hold6)
end api
API contacts.ID.HEAD
API contacts.ID.GET
KeyID = EndpointSegment
// Create a new specific contacts resource object using the passed in resource ID to initialize the content.
objResource = HTTP_Resource_Services('GetObject', 'CONTACTS', KeyID, '', '', '', '', '', '', '', '', 1)
If Error_Services('NoError') then
// Add _links sub-properties for HAL implementation.
CollectionURL = ParentURL
Names = 'self,collection'
URLs = FullEndpointURL : ',' : CollectionURL
HTTP_Resource_Services('AddLinkRelations', objResource, Names, URLs)
end
If Error_Services('NoError') then
// If there is a picture related to this contact, add another _links sub-property for the URL.
PictureValue = SRP_JSON(objResource, 'GetValue', 'picture', '')
If PictureValue NE '' then
ImageURL = FullEndpointURL : '/picture'
HTTP_Resource_Services('AddLinkRelations', objResource, 'picture', ImageURL)
end
end
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end api
API contacts.ID.PATCH
KeyID = EndpointSegment
HTTP_Resource_Services('PatchDatabaseItem', 'CONTACTS', FullEndpointURL, KeyID)
end api
API contacts.ID.PUT
KeyID = EndpointSegment
HTTP_Resource_Services('PutDatabaseItem', 'CONTACTS', FullEndpointURL, KeyID)
end api
API contacts.ID.DELETE
KeyID = EndpointSegment
HTTP_Resource_Services('DeleteDatabaseItem', 'CONTACTS', KeyID)
end api
API contacts.ID.first_name.HEAD
API contacts.ID.first_name.GET
KeyID = ParentSegment
objResource = HTTP_Resource_Services('GetObject', 'CONTACTS', KeyID, 'first_name')
If Error_Services('NoError') then
// Add _links sub-properties for HAL implementation.
ResourceURL = ParentURL
Names = 'self' : @FM : 'resource'
URLs = FullEndpointURL : @FM : ResourceURL
HTTP_Resource_Services('AddLinkRelations', objResource, Names, URLs)
end
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end api
API contacts.ID.first_name.PATCH
KeyID = ParentSegment
HAL = HTTP_Resource_Services('PatchDatabaseItem', 'CONTACTS', FullEndpointURL, KeyID, 'first_name')
end api
API contacts.ID.last_name.HEAD
API contacts.ID.last_name.GET
KeyID = ParentSegment
objResource = HTTP_Resource_Services('GetObject', 'CONTACTS', KeyID, 'last_name')
If Error_Services('NoError') then
// Add _links sub-properties for HAL implementation.
ResourceURL = ParentURL
Names = 'self' : @FM : 'resource'
URLs = FullEndpointURL : @FM : ResourceURL
HTTP_Resource_Services('AddLinkRelations', objResource, Names, URLs)
end
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end api
API contacts.ID.last_name.PATCH
KeyID = ParentSegment
HAL = HTTP_Resource_Services('PatchDatabaseItem', 'CONTACTS', FullEndpointURL, KeyID, 'last_name')
end api
API contacts.ID.first_name.PUT
KeyID = ParentSegment
HAL = HTTP_Resource_Services('PatchDatabaseItem', 'CONTACTS', FullEndpointURL, KeyID, 'first_name')
end api
API contacts.ID.last_name.PUT
KeyID = ParentSegment
HAL = HTTP_Resource_Services('PatchDatabaseItem', 'CONTACTS', FullEndpointURL, KeyID, 'last_name')
end api

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,380 @@
Function Error_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Error_Services
Description : Handler program for all error services.
Notes : Application errors should be logged using the Error Services module. There are a few methodological
assumptions built into way errors are managed which are important to understand in order to properly
work with Error Services:
- The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to
the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger
this will appear backwards since the originating procedure always appears at the bottom of the
list and the current routine appears at the top of the list. We are using this orientation because
it is common to refer to the process of calling other procedures as 'drilling down'.
- The reason for defining the orientation of the call stack is because Error_Services allows for
multiple error conditions to be appended to an original error. In most cases this will happen when
a procedure at the bottom of the stack generates an error condition and then returns to its
calling procedure. This higher level procedure can optionally add more information relevant to
itself. This continues as the call stack 'bubbles' its way back to the top to where the
originating procedure is waiting.
- Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus)
preserve their error state until explicitly cleared. This can hinder the normal execution of code
since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists.
Our philosophy is that error conditions should automatically be cleared before a new procedure
is executed to avoid this problem. However, the nature of Basic+ does not make this easy to
automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our
philosophy then it should include a call into the 'Clear' service request at the top of the
program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.)
- Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any
error conditions that were set before.
- The 'Set' service request is the equivelent to the various forms of setting an error within Basic+
(e.g., Set_Status, Set_FSError, Set_EventStatus). This will clear out any pre-existing error(s)
first (see 'Clear' service request description below). In most cases the 'Add' service request
(see below) should be used since error conditions are intended to be automatically cleared by
service modules or properly managed stored procedures.
- The 'Add' service request is similar to the 'Set' service request but it will not clear out any
pre-existing errors. Using 'Add', the error conditions can be stacked allowing the higher level
calling procedures the ability to contribute to the existing error or add additional errors.
- The 'Clear' service request will reset all of the error condition flags.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
History : (Date, Initials, Notes)
12/28/12 dmb Original programmer.
12/31/12 dmb Add hooks for various service requests. Add comments in the Notes section to explain the
theory of operation of Error Services.
01/01/13 dmb Add functionality to the Set, Add, GetMessage, and GetMessages service requests.
01/02/13 dmb Remove reference to SERVICES_SETUP and put the Assigned command lines directly into this
code to avoid infinite loop problem.
01/05/13 dmb Added HasError service request.
03/13/13 dmb [SRPFW-9] Added NoError service request.
10/01/13 dmb [SRPFW-18] Replace APP_INSERTS with LOGICAL and declare Error_Services.
10/06/13 dmb [SRPFW-17] Retrofit to use the default FrameWorks system font.
03/20/17 fjt [SRPFW-160] Conversion to EB+; addition of justification parameter to display.
10/09/17 dmb Add SendRuntimeAlert service to act as a debugger intercept process.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$Insert MSG_EQUATES
$insert RTI_DEBUG_COMMON
$insert SRPMail_Inserts
Equ Segoe_UI$ to 'Segoe UI' : @SVM : -12 : @SVM : 400 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0
// Make sure any request parameters which have not been assigned are nulled.
// Normally these would be referenced in the SERVICES_SETUP insert but there is a call to ERROR_SERVICES in that
// insert which causes an infinite loop to occur.
If Assigned(Service) else Service = ''
If Assigned(Error) else Error = ''
If Assigned(Param1) else Param1 = ''
If Assigned(Param2) else Param2 = ''
If Assigned(Param3) else Param3 = ''
If Assigned(Param4) else Param4 = ''
If Assigned(Param5) else Param5 = ''
If Assigned(Param6) else Param6 = ''
If Assigned(Param7) else Param7 = ''
If Assigned(Param8) else Param8 = ''
If Assigned(Param9) else Param9 = ''
If Assigned(Param10) else Param10 = ''
If Assigned(Response) else Response = ''
AutoDisplayErrors = False$ ; // Set this to True$ when debugging so all errors will automatically display.
Common /ErrorServices/ ErrorMessages@, ErrorSources@, ErrorCodes@, RetStacks@, Unused5@, Unused6@, Unused7@, Unused8@
Declare function RetStack, Error_Services, SRPSendMail
Declare subroutine Error_Services
GoToService else
Error_Services('Set', Service : ' is not a valid service request within the Error services module.')
end
Return Response else ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// Set
//
// Param1 - Error message. Messages should be fairly descriptive.
//
// Sets an error to the stack. This will automatically clear any existing error conditions first so this error will
// be the only one on the stack.
//----------------------------------------------------------------------------------------------------------------------
Service Set(ErrorMessage)
Error_Services('Clear')
Error_Services('Add', ErrorMessage)
If AutoDisplayErrors then Error_Services('DisplayError')
End Service
//----------------------------------------------------------------------------------------------------------------------
// Add
//
// Param1 - Error message. Messages should be fairly descriptive.
//
// Adds an error to the stack. This will not clear existing error conditions first. It is intended to allow higher level
// routines to add more information to an existing error condition or simply to maintain an ongoing error log for some
// troubleshooting or debugging purposes.
//----------------------------------------------------------------------------------------------------------------------
Service Add(ErrorMessage)
CurStack = RetStack()
AtSelf = CurStack[1, @FM] ; // AtSelf should be the name of this routine (e.g., ERROR_SERVICES)
Loop
CurRoutine = CurStack[1, @FM] ; // Get the next routine from the program call stack.
Until CurRoutine _NEC AtSelf
CurStack = Delete(CurStack, 1, 0, 0) ; // Remove any self-references from the program call stack.
Repeat
Convert @FM to @VM in CurStack ; // Convert the delimiter so it can be added to the global common.
If Len(ErrorMessages@) then
ErrorMessages@ := @FM : ErrorMessage
RetStacks@ := @FM : CurStack
end else
ErrorMessages@ = ErrorMessage
RetStacks@ = CurStack
end
If AutoDisplayErrors then Error_Services('DisplayError')
End Service
//----------------------------------------------------------------------------------------------------------------------
// Clear
//
// Clears all error conditions and related information.
//----------------------------------------------------------------------------------------------------------------------
Service Clear()
ErrorMessages@ = ''
ErrorSources@ = ''
ErrorCodes@ = ''
RetStacks@ = ''
End Service
//----------------------------------------------------------------------------------------------------------------------
// GetMessage
//
// Returns the most current error message.
//----------------------------------------------------------------------------------------------------------------------
Service GetMessage()
Response = ErrorMessages@[-1, 'B' : @FM]
End Service
//----------------------------------------------------------------------------------------------------------------------
// GetMessages
//
// Returns the stack of error messages. This will be @FM delimited.
//----------------------------------------------------------------------------------------------------------------------
Service GetMessages()
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
Response = ErrorMessages@
End Service
//----------------------------------------------------------------------------------------------------------------------
// HasError
//
// Returns True if there is an error condition, False if there is no error condition. Caller will still need to use
// the GetMessage or GetMessages service to determine what the error is. The HasError service allows the caller to
// embed the Error_Services service call inside of a conditional statement like this:
//
// If Error_Services('HasError') then
// * An error has occured. Proceed accordingly.
// ErrorMessage = Error_Services('GetMessage')
// end else
// * No error has occured.
// end
//----------------------------------------------------------------------------------------------------------------------
Service HasError()
If Len(ErrorMessages@) then
Response = True$
end else
Response = False$
end
End Service
//----------------------------------------------------------------------------------------------------------------------
// NoError
//
// Returns True if there are no error conditions, False if there is an error condition. This is the opposite of the
// HasError service and exists for improved readability.
//----------------------------------------------------------------------------------------------------------------------
Service NoError()
If Len(ErrorMessages@) then
Response = False$
end else
Response = True$
end
End Service
//----------------------------------------------------------------------------------------------------------------------
// DisplayError
//
// Displays the current error message to the end user.
//----------------------------------------------------------------------------------------------------------------------
Service DisplayError(Justification)
ErrorMessage = Error_Services('GetMessage')
If Len(ErrorMessage) then
MsgStruct = ''
MsgStruct<MTEXT$> = ErrorMessage
MsgStruct<MTYPE$> = 'BO'
MsgStruct<MMODAL$> = 'W'
MsgStruct<MICON$> = '!'
MsgStruct<MCOL$> = -1
MsgStruct<MROW$> = -1
MsgStruct<MJUST$> = Justification
MsgStruct<MCAPTION$> = 'Error Services'
MsgStruct<MFONT$> = Segoe_UI$
Msg(@Window, MsgStruct)
end
End Service
Service GetSource()
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
Response = '<Service Response>'
End Service
Service GetSources()
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
Response = '<Service Response>'
End Service
Service GetCode()
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
Response = '<Service Response>'
End Service
Service GetCodes()
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
Response = '<Service Response>'
End Service
Service GetStackTrace()
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
Response = '<Service Response>'
End Service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////?
//----------------------------------------------------------------------------------------------------------------------
// SendRuntimeAlert
//
// Sends out an email alert when this service is called as a debugger intercept.
//----------------------------------------------------------------------------------------------------------------------
SendRuntimeAlert:
Done = False$
Error = False$
Program = Curr_Program@
MsgSent = ''
If Program EQ '' then Program = 'Error Services'
ConfigFile = ''
ConfigFile<1> = SendUsing_Port$
ConfigFile<2> = ''
ConfigFile<3> = '' ; // Server port
ConfigFile<4> = '' ; // Mail server
ConfigFile<5> = True$ ; // Authenticate
ConfigFile<6> = '' ; // Username
ConfigFile<7> = '' ; // Password
ConfigFile<8> = False$ ; // Use SSL
Text = ''
Text<-1> = 'App: ' : @APPID<1>
Text<-1> = 'Window: ' : @WINDOW
Text<-1> = 'User: ' : @USERNAME
Text<-1> = 'Station: ' : @STATION
Text<-1> = ' '
Text<-1> = 'SP Status: ' : SPStatus@
Text<-1> = 'SP Stat Code: ' : SPStatCode@
Text<-1> = 'Program: ' : Program
Text<-1> = 'Call Depth: ' : CallDepth@
Text<-1> = 'Line No: ' : LineNo@
Text<-1> = ' '
Text<-1> = 'Stack: '
Text<-1> = CallStack@
Convert \00\ TO ',' in Text
Swap @VM with ':@VM:' IN Text
Swap @FM with Char(13) : Char(10) IN Text
Swap @TM with Char(13) : Char(10) IN Text
SentFrom = ''
SentTo = ''
Message = ''
Message<1> = '' : Program ; // Subject
Message<2> = SentFrom ; // From (email address)
Message<3> = SentTo ; // Send to (email address)
Message<5> = '' ; // Blind Carbon Copy (email address)
Message<6> = '' ; // Reply To (email address)
Message<7> = 'TEXT' ; // Content Type (TEXT or HTML)
Message<8> = Text ; // Content / Body
Message<9> = '' ; // Attachment(s) (path to file name(s))
MsgSent = SRPSendMail(Message, ConfigFile)
return

View File

@ -0,0 +1,856 @@
Function HTTPClient_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTPClient_Services
Description : Handler program for all module related services.
Notes : The generic parameters should contain all the necessary information to process the services. Often
this will be information like the data Record and Key ID.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
03/28/16 dmb [SRPFW-120] Original programmer.
07/01/17 dmb [SRPFW-184] Refactor using Enhanced BASIC+ syntax.
05/19/18 dmb [SRPFW-235] Check for content in the HeaderList variable before calling the For Each loop.
11/15/18 dmb [SRPFW-238] Add ClientCertPath argument to the SendHTTPRequest service to support
client-side certificates.
02/28/19 dmb Change UseXMLHTTP argument to UseClientXMLHTTP in the SendHTTPRequest service to make it
easier to interpret.
02/09/20 dmb [SRPFW-309] Fix a bug in the SendHTTPRequest service so that request headers are properly
parsed. All colons were erroneously being converted to @VM instead of the first colon (which
separated the header name from the header value).
02/09/20 dmb [SRPFW-309] Update the SetResponseHeaderField service to better support Set-Cookie headers.
Allow multiple cookie names to be stored but only store the value of the last cookie name
if it is duplicated.
02/09/20 dmb [SRPFW-309] Update the GetResponseHeaderField by adding a Delimiter argument so the caller
can specify an alternative delimiter for the values being returned.
02/09/20 dmb [SRPFW-309] Add GetCookies service to make it easier to view all cookies returned in the
response.
02/09/20 dmb [SRPFW-309] Add GetCookie service to make it easier to see the entire cookie string of a
specified cookie.
02/10/20 dmb [SRPFW-309] Update the GetCookie service to include an IgnoreAttributes argument. If this
is True$, then only the cookie name and value will be returned.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
Equ CRLF$ to \0D0A\
// The readyState property will have this value when the request has returned from the server.
// http://msdn.microsoft.com/en-us/library/ms753800(v=vs.85).aspx
Equ HTTP_COMPLETED$ to 4
Common /HTTPClientServices/ RequestHeaderFields@, RequestHeaderValues@, ResponseHeaderFields@, ResponseHeaderValues@, ResponseStatusCode@, ResponseStatusPhrase@, ResponseBody@, TimeoutDuration@
Declare function SRP_COM, HTTPClient_Services, GetTickCount, OLECreateInstance, OLEGetProperty, OLECallMethod, OLEStatus
Declare subroutine SRP_COM, HTTPClient_Services, OLEPutProperty
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
Options RESPONSEHEADERNAMES = 'Access-Control-Allow-Headers', 'Access-Control-Allow-Methods', 'Access-Control-Allow-Origin', 'Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-Location', 'Content-Disposition', 'Content-Type', 'Date', 'Expires', 'Last-Modified', 'Link', 'Location', 'Retry-After', 'Server', 'Set-Cookie', 'Transfer-Encoding', 'Vary', 'WWW-Authenticate',
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SendHTTPRequest
//
// Method - The HTTP method to submit to the server. - [Required]
// URL - The URL receiving the HTTP request. - [Required]
// HeaderList - An @FM/@VM list of request header names and values. - [Optional]
// Body - The request body to be sent to the server. - [Optional]
// ProxyUser - Username needed to authenticate against a proxy server. - [Optional]
// ProxyPassword - Password needed to authenticate against a proxy server. - [Optional]
// UseAsynchronous - Flag to determine if the HTTP request should be processed asynchronously. Default is True.
// - [Optional]
// UseClientXMLHTTP - Flag to determine if client XMLHTTP or server XMLHTTP should be used. Default is server XMLHTTP.
// - [Optional]
// ClientCertPath - Path to a client-side certificate. This is usually in Location\Certificate Store\Subject format.
// - [Optional]
//
// Calls the indicated HTTP web service routine.
//----------------------------------------------------------------------------------------------------------------------
Service SendHTTPRequestOLE(Method, URL, HeaderList, Body, ProxyUser, ProxyPassword, UseAsynchronous, UseClientXMLHTTP, ClientCertPath)
// Defaults.
If UseAsynchronous NE False$ then UseAsynchronous = True$
If UseClientXMLHTTP NE True$ then UseClientXMLHTTP = False$
If (Method NE '') AND (URL NE '') then
// Make sure all prior response settings are cleared before performing the next HTTP request.
HTTPClient_Services('ClearResponseSettings')
// Attempt to get a handle for the best XMLHTTP object.
objXMLHTTP = ''
If UseClientXMLHTTP then
ServerPrefix = ''
end else
ServerPrefix = 'Server'
end
XMLHTTPProgID = 'Msxml2.' : ServerPrefix : 'XMLHTTP.6.0'
objXMLHTTP = OLECreateInstance(XMLHTTPProgID)
Status = OLEStatus()
If Status then
XMLHTTPProgID = 'Msxml2.' : ServerPrefix : 'XMLHTTP.3.0'
objXMLHTTP = OLECreateInstance(XMLHTTPProgID)
Status = OLEStatus()
If Status then
XMLHTTPProgID = 'Msxml2.' : ServerPrefix : 'XMLHTTP'
objXMLHTTP = OLECreateInstance(XMLHTTPProgID)
Status = OLEStatus()
If Status then
Error = 'Unable to create a handle to the XMLHTTP object in the ' : Service : ' service.'
Error := ' OLE Error: ' : Status
Error_Services('Add', Error)
end
end
end
If Error_Services('NoError') then
// Invoke the XMLHTTP object's open method to initialize a request.
rv = OLECallMethod(objXMLHTTP, 'open', Method, URL, UseAsynchronous, ProxyUser, ProxyPassword)
Status = OLEStatus()
If Status then
Error = 'Error calling the open method for the XMLHTTP object in the ' : Service : ' service.'
Error := ' OLE Error: ' : Status
Error_Services('Add', Error)
end
end
* If Error_Services('NoError') then
* // Set the request header names and values. This will add or update any header fields passed in through this
* // service with those have may have been previously set using the SetRequestHeaderFields or
* // SetRequestHeaderField already.
* If Len(HeaderList) then HTTPClient_Services('SetRequestHeaderFields', HeaderList)
* // Now get all of the request header fields.
* HeaderList = HTTPClient_Services('GetRequestHeaderFields')
* If Error_Services('NoError') then
* If HeaderList NE '' then
* For Each HeaderPair in HeaderList using @FM
* HeaderName = HeaderPair<0, 1>
* HeaderValue = HeaderPair<0, 2>
* SRP_COM(objXMLHTTP, 'CALL', 'setRequestHeader', HeaderName, HeaderValue)
* If SRP_COM('', 'HASERROR') then
* Error = 'Error setting the setRequestHeader property for the ' : HeaderName : ' field in the XMLHTTP object in the ' : Service : ' service.'
* Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
* Error_Services('Add', Error)
* end
* Next HeaderPair
* end
* end
* end
* If ClientCertPath NE '' then
* If Error_Services('NoError') then
* // Invoke the XMLHTTP object's setOption method to invoke a certificate.
* rv = SRP_COM(objXMLHTTP, 'CALL', 'setOption', 3, ClientCertPath)
* If SRP_COM('', 'HASERROR') then
* Error = 'Error calling the setOption method for the XMLHTTP object in the ' : Service : ' service.'
* Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
* Error_Services('Add', Error)
* end
* end
* end
If Error_Services('NoError') then
// Invoke the XMLHTTP object's send method to submit the request to the server.
rv = OLECallMethod(objXMLHTTP, 'send', Body)
Status = OLEStatus()
If Status then
Error = 'Error calling the send method for the XMLHTTP object in the ' : Service : ' service.'
Error := ' OLE Error: ' : Status
Error_Services('Add', Error)
end
end
If Error_Services('NoError') then
If UseAsynchronous then
StartTime = GetTickCount()
TimeoutDuration = HTTPClient_Services('GetTimeoutDuration')
TimedOut = False$
Loop
ReadyState = OLEGetProperty(objXMLHTTP, 'readyState')
CurrentTime = GetTickCount()
ElapsedTime = Int((CurrentTime - StartTime) / 1000)
TimedOut = ElapsedTime GE TimeoutDuration
While (ReadyState NE HTTP_COMPLETED$) AND Not(TimedOut)
Repeat
end
// Check the XMLHTTP object's responseBody property to get the server's response.
Response = OLEGetProperty(objXMLHTTP, 'responseBody')
Response1 = OLEGetProperty(objXMLHTTP, 'responseText')
Response2 = objXMLHTTP->responseBody
Response3 = objXMLHTTP->responseText
Status = OLEStatus()
If Status then
Error = 'Error getting the responseBody property for the XMLHTTP object in the ' : Service : ' service.'
Error := ' OLE Error: ' : Status
Error_Services('Add', Error)
Response = ''
end else
HTTPClient_Services('SetResponseBody', Response)
end
end
If Error_Services('NoError') then
// If the request was successful, get the response status code, phrase, and response headers and set them
// using HTTPClient_Services so the caller can retrieve is desired.
Code = OLEGetProperty(objXMLHTTP, 'status')
Phrase = Trim(OLEGetProperty(objXMLHTTP, 'statusText'))
HTTPClient_Services('SetResponseStatusCode', Code)
HTTPClient_Services('SetResponseStatusPhrase', Phrase)
ResponseHeaders = OLECallMethod(objXMLHTTP, 'getAllResponseHeaders')
Swap CRLF$ with @FM in ResponseHeaders
For Each ResponseHeader in ResponseHeaders using @FM
Name = ResponseHeader[1, 'F:']
Value = Trim(ResponseHeader[Col2() + 1, 9999])
If (Name NE '') AND (Value NE '') then
HTTPClient_Services('SetResponseHeaderField', Name, Value)
end
Next ResponseHeader
end
// Make sure all prior request settings are cleared so future HTTP request won't be affected.
Error = Error_Services('GetMessage') ; // Get any pre-existing errors so they can be preserved.
HTTPClient_Services('ClearRequestSettings') ; // This will automatically clear the error stack.
Error_Services('Set', Error) ; // Restore any errors so the caller can check for them.
end else
Error_Services('Add', 'Method or URL argument was missing from the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SendHTTPRequest
//
// Method - The HTTP method to submit to the server. - [Required]
// URL - The URL receiving the HTTP request. - [Required]
// HeaderList - An @FM/@VM list of request header names and values. - [Optional]
// Body - The request body to be sent to the server. - [Optional]
// ProxyUser - Username needed to authenticate against a proxy server. - [Optional]
// ProxyPassword - Password needed to authenticate against a proxy server. - [Optional]
// UseAsynchronous - Flag to determine if the HTTP request should be processed asynchronously. Default is True.
// - [Optional]
// UseClientXMLHTTP - Flag to determine if client XMLHTTP or server XMLHTTP should be used. Default is server XMLHTTP.
// - [Optional]
// ClientCertPath - Path to a client-side certificate. This is usually in Location\Certificate Store\Subject format.
// - [Optional]
//
// Calls the indicated HTTP web service routine.
//----------------------------------------------------------------------------------------------------------------------
Service SendHTTPRequest(Method, URL, HeaderList, Body, ProxyUser, ProxyPassword, UseAsynchronous, UseClientXMLHTTP, ClientCertPath)
// Defaults.
If UseAsynchronous NE False$ then UseAsynchronous = True$
If UseClientXMLHTTP NE True$ then UseClientXMLHTTP = False$
If (Method NE '') AND (URL NE '') then
// Make sure all prior response settings are cleared before performing the next HTTP request.
HTTPClient_Services('ClearResponseSettings')
// Attempt to get a handle for the best XMLHTTP object.
objXMLHTTP = ''
If UseClientXMLHTTP then
ServerPrefix = ''
end else
ServerPrefix = 'Server'
end
XMLHTTPProgID = 'Msxml2.' : ServerPrefix : 'XMLHTTP.6.0'
If SRP_COM(objXMLHTTP, 'CREATE', XMLHTTPProgID) else
XMLHTTPProgID = 'Msxml2.' : ServerPrefix : 'XMLHTTP.3.0'
If SRP_COM(objXMLHTTP, 'CREATE', XMLHTTPProgID) else
XMLHTTPProgID = 'Msxml2.' : ServerPrefix : 'XMLHTTP'
If SRP_COM(objXMLHTTP, 'CREATE', XMLHTTPProgID) else
Error = 'Unable to create a handle to the XMLHTTP object in the ' : Service : ' service.'
If SRP_COM('', 'HASERROR') then
Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
end
Error_Services('Add', Error)
end
end
end
If Error_Services('NoError') then
// Invoke the XMLHTTP object's open method to initialize a request.
SRP_COM(objXMLHTTP, 'CALL', 'open', Method, URL, UseAsynchronous, ProxyUser, ProxyPassword)
If SRP_COM('', 'HASERROR') then
Error = 'Error calling the open method for the XMLHTTP object in the ' : Service : ' service.'
Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
Error_Services('Add', Error)
end
end
If Error_Services('NoError') then
// Set the request header names and values. This will add or update any header fields passed in through this
// service with those have may have been previously set using the SetRequestHeaderFields or
// SetRequestHeaderField already.
If Len(HeaderList) then HTTPClient_Services('SetRequestHeaderFields', HeaderList)
// Now get all of the request header fields.
HeaderList = HTTPClient_Services('GetRequestHeaderFields')
If Error_Services('NoError') then
If HeaderList NE '' then
For Each HeaderPair in HeaderList using @FM
HeaderName = HeaderPair<0, 1>
HeaderValue = HeaderPair<0, 2>
SRP_COM(objXMLHTTP, 'CALL', 'setRequestHeader', HeaderName, HeaderValue)
If SRP_COM('', 'HASERROR') then
Error = 'Error setting the setRequestHeader property for the ' : HeaderName : ' field in the XMLHTTP object in the ' : Service : ' service.'
Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
Error_Services('Add', Error)
end
Next HeaderPair
end
end
end
If ClientCertPath NE '' then
If Error_Services('NoError') then
// Invoke the XMLHTTP object's setOption method to invoke a certificate.
rv = SRP_COM(objXMLHTTP, 'CALL', 'setOption', 3, ClientCertPath)
If SRP_COM('', 'HASERROR') then
Error = 'Error calling the setOption method for the XMLHTTP object in the ' : Service : ' service.'
Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
Error_Services('Add', Error)
end
end
end
If Error_Services('NoError') then
// Invoke the XMLHTTP object's send method to submit the request to the server.
rv = SRP_COM(objXMLHTTP, 'CALL', 'send', Body)
If SRP_COM('', 'HASERROR') then
Error = 'Error calling the send method for the XMLHTTP object in the ' : Service : ' service.'
Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
Error_Services('Add', Error)
end
end
If Error_Services('NoError') then
If UseAsynchronous then
StartTime = GetTickCount()
TimeoutDuration = HTTPClient_Services('GetTimeoutDuration')
TimedOut = False$
Loop
ReadyState = SRP_COM(objXMLHTTP, 'GET', 'readyState')
CurrentTime = GetTickCount()
ElapsedTime = Int((CurrentTime - StartTime) / 1000)
TimedOut = ElapsedTime GE TimeoutDuration
While (ReadyState NE HTTP_COMPLETED$) AND Not(TimedOut)
Repeat
end
// Check the XMLHTTP object's responseBody property to get the server's response.
* Response = SRP_COM(objXMLHTTP, 'GET', 'responseBody')
Response = SRP_COM(objXMLHTTP, 'GET', 'responseText')
If SRP_COM('', 'HASERROR') then
Error = 'Error getting the responseBody property for the XMLHTTP object in the ' : Service : ' service.'
Error := ' SRP_COM Error: ' : SRP_COM('', 'ERROR')
Error_Services('Add', Error)
Response = ''
end else
HTTPClient_Services('SetResponseBody', Response)
end
end
If Error_Services('NoError') then
// If the request was successful, get the response status code, phrase, and response headers and set them
// using HTTPClient_Services so the caller can retrieve is desired.
Code = SRP_COM(objXMLHTTP, 'GET', 'status')
Phrase = Trim(SRP_COM(objXMLHTTP, 'GET', 'statusText'))
HTTPClient_Services('SetResponseStatusCode', Code)
HTTPClient_Services('SetResponseStatusPhrase', Phrase)
ResponseHeaders = SRP_COM(objXMLHTTP, 'CALL', 'getAllResponseHeaders')
Swap CRLF$ with @FM in ResponseHeaders
For Each ResponseHeader in ResponseHeaders using @FM
Name = ResponseHeader[1, 'F:']
Value = Trim(ResponseHeader[Col2() + 1, 9999])
If (Name NE '') AND (Value NE '') then
HTTPClient_Services('SetResponseHeaderField', Name, Value)
end
Next ResponseHeader
end
// Release the handle to the XMLHTTP object in case it was created.
SRP_COM(objXMLHTTP, 'RELEASE')
// Make sure all prior request settings are cleared so future HTTP request won't be affected.
Error = Error_Services('GetMessage') ; // Get any pre-existing errors so they can be preserved.
HTTPClient_Services('ClearRequestSettings') ; // This will automatically clear the error stack.
Error_Services('Set', Error) ; // Restore any errors so the caller can check for them.
end else
Error_Services('Add', 'Method or URL argument was missing from the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetRequestHeaderFields
//
// HeaderList - An @FM/@VM list of request header fields and their values. - [Required]
//
// Sets the Request Header Fields as indicated by the HeaderList argument. The HeaderList should not be formatted as a
// list rather than an associated multivalue array. This is easier for the developer to manage in the code that calls
// this service.
//----------------------------------------------------------------------------------------------------------------------
Service SetRequestHeaderFields(HeaderList)
If HeaderList NE '' then
For Each HeaderPair in HeaderList using @FM
HeaderName = HeaderPair<0, 1>
HeaderValue = HeaderPair<0, 2>
HTTPClient_Services('SetRequestHeaderField', HeaderName, HeaderValue)
Next HeaderPair
end else
Error_Services('Add', 'HeaderList argument was missing from the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetRequestHeaderField
//
// Name - Header Field Name to set. - [Required]
// Value - Value for the header field. This will be Trimmed to enforce proper formatting. - [Required]
//
// Sets the indicated Request Header Field with the indicated value.
//----------------------------------------------------------------------------------------------------------------------
Service SetRequestHeaderField(Name, Value)
If (Name NE '') AND (Value NE '') then
SearchName = Name
Convert @Lower_Case to @Upper_Case in SearchName
SearchFields = RequestHeaderFields@
Convert @Lower_Case to @Upper_Case in SearchFields
Locate SearchName in SearchFields using @FM setting fPos else
fPos = Count(RequestHeaderFields@, @FM) + (RequestHeaderFields@ NE '') + 1
end
RequestHeaderFields@<fPos> = Name
RequestHeaderValues@<fPos> = Trim(Value)
end else
Error_Services('Add', 'The Name or Value argument is missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetRequestHeaderFields
//
// Returns all of the Request Header Field names and values. This returns an @FM/@VM list of names and values.
//----------------------------------------------------------------------------------------------------------------------
Service GetRequestHeaderFields()
HeaderFieldBlock = ''
If RequestHeaderFields@ NE '' then
NumFields = Count(RequestHeaderFields@, @FM) + (RequestHeaderFields@ NE '')
For FieldCnt = 1 to NumFields
HeaderFieldBlock := RequestHeaderFields@<FieldCnt> : @VM : RequestHeaderValues@<FieldCnt> : @FM
Next FieldCnt
HeaderFieldBlock[-1, 1] = ''
end
Response = HeaderFieldBlock
end service
//----------------------------------------------------------------------------------------------------------------------
// GetRequestHeaderField
//
// Name - Header Field Name to get. - [Required]
//
// Returns the value previously set for the indicated Request Header Field.
//----------------------------------------------------------------------------------------------------------------------
Service GetRequestHeaderField(Name)
Value = ''
If Name NE '' then
SearchName = Name
Convert @Lower_Case to @Upper_Case in SearchName
SearchFields = RequestHeaderFields@
Convert @Lower_Case to @Upper_Case in SearchFields
Locate SearchName in SearchFields using @FM setting fPos then
Value = RequestHeaderValues@<fPos>
end else
Error_Services('Add', Name : ' is not a header field in the request.')
end
end else
Error_Services('Add', 'The Name argument is missing in the ' : Service : ' service.')
end
Response = Value
end service
//----------------------------------------------------------------------------------------------------------------------
// SetResponseHeaderField
//
// Name - Header Field Name to set. - [Required]
// Value - Value for the header field. This will be Trimmed to enforce proper formatting. - [Required]
//
// Sets the indicated Response Header Field with the indicated value.
//----------------------------------------------------------------------------------------------------------------------
Service SetResponseHeaderField(Name, Value)
If (Name NE '') AND (Value NE '') then
SearchName = Name
Convert @Lower_Case to @Upper_Case in SearchName
SearchFields = ResponseHeaderFields@
Convert @Lower_Case to @Upper_Case in SearchFields
Locate SearchName in SearchFields using @FM setting fPos else
fPos = Count(ResponseHeaderFields@, @FM) + (ResponseHeaderFields@ NE '') + 1
end
ResponseHeaderFields@<fPos> = Name
PreviousValue = ResponseHeaderValues@<fPos>
If PreviousValue EQ '' then
ResponseHeaderValues@<fPos> = Trim(Value)
end else
If Name EQ 'Set-Cookie' then
// Unlike other response headers, Set-Cookie can have multiple entries. However, if more than one
// cookie of a particular name exists then only store the last entry.
SetCookieFound = False$
CookieName = Value[1, 'F='][1, 'F '][1, 'F;']
For Each HeaderField in ResponseHeaderFields@ using @FM setting fPos
If HeaderField EQ 'Set-Cookie' then
SetCookieFound = True$
end
Until SetCookieFound EQ True$
Next HeaderField
If SetCookieFound EQ True$ then
// Set-Cookie was found. Check to see if the cookie name has already been added.
CookieNameFound = False$
CookieValues = ResponseHeaderValues@<fPos>
For Each CookieValue in CookieValues using @VM setting vPos
MatchCookieName = CookieValue[1, 'F='][1, 'F '][1, 'F;']
If CookieName EQ MatchCookieName then
CookieNameFound = True$
end
Until CookieNameFound EQ True$
Next CookieValue
If CookieNameFound EQ True$ then
// Cookie name already exists. Replace the old value with the new one.
ResponseHeaderValues@<fPos, vPos> = Trim(Value)
end else
// This is a new cookie name. Append the Set-Cookie value to the list.
ResponseHeaderValues@<fPos, -1> = Trim(Value)
end
end else
// No cookies have been set yet.
ResponseHeaderValues@<fPos> = Trim(Value)
end
end else
ResponseHeaderValues@<fPos> = PreviousValue : ' ;' : Trim(Value)
end
end
end else
Error_Services('Add', 'The Name or Value argument is missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResponseHeaderFields
//
// Returns all of the Response Header Field names and values. This returns an @FM/@VM list of names and values.
//----------------------------------------------------------------------------------------------------------------------
Service GetResponseHeaderFields()
HeaderFieldBlock = ''
If ResponseHeaderFields@ NE '' then
NumFields = Count(ResponseHeaderFields@, @FM) + (ResponseHeaderFields@ NE '')
For FieldCnt = 1 to NumFields
HeaderFieldBlock := ResponseHeaderFields@<FieldCnt> : @VM : ResponseHeaderValues@<FieldCnt> : @FM
Next FieldCnt
HeaderFieldBlock[-1, 1] = ''
end else
Error_Services('Add', 'There are no response header fields get.')
end
Response = HeaderFieldBlock
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResponseHeaderField
//
// Name - Header Field Name to get. - [Required]
// Delimiter - Delimiter to use for multiple values. Default is '; ' for all header fields except for Set-Cookie.
// Set-Cookie defaults to @VM. - [Optional]
//
// Returns the value previously set for the indicated Response Header Field. The Name argument is case-insensitive but
// if the indicated Response Header Field has not been set then an error condition will be set.
//----------------------------------------------------------------------------------------------------------------------
Service GetResponseHeaderField(Name=RESPONSEHEADERNAMES, Delimiter)
Value = ''
If Name NE '' then
SearchName = Name
Convert @Lower_Case to @Upper_Case in SearchName
SearchFields = ResponseHeaderFields@
Convert @Lower_Case to @Upper_Case in SearchFields
Locate SearchName in SearchFields using @FM setting fPos then
Value = ResponseHeaderValues@<fPos>
If Delimiter NE '' then
If Name EQ 'Set-Cookie' then
Convert @VM to Delimiter in Value
end else
Swap '; ' with Delimiter in Value
end
end
end else
Error_Services('Add', Name : ' is not a header field in the response.')
end
end else
Error_Services('Add', 'The Name argument is missing in the ' : Service : ' service.')
end
Response = Value
end service
//----------------------------------------------------------------------------------------------------------------------
// GetCookies
//
// Delimiter - Delimiter to use for multiple cookies. Default is @FM - [Optional]
//
// Returns all cookie strings from the response headers.
//----------------------------------------------------------------------------------------------------------------------
Service GetCookies(Delimiter)
If Delimiter EQ '' then Delimiter = @FM
Cookies = HTTPClient_Services('GetResponseHeaderField', 'Set-Cookie', Delimiter)
Response = Cookies
end service
//----------------------------------------------------------------------------------------------------------------------
// GetCookie
//
// Name - Name of the cookie to get. - [Required]
// IgnoreAttributes - Boolean flag to indicate if the cookie's attributes should be removed when returning the cookie.
// Default value is False$. - [Optional]
//
// Returns the value for the indicated cookie name.
//----------------------------------------------------------------------------------------------------------------------
Service GetCookie(Name, IgnoreAttributes=BOOLEAN)
If IgnoreAttributes NE True$ then IgnoreAttributes = False$
Cookie = ''
If Name NE '' then
CookieNameFound = False$
Cookies = HTTPClient_Services('GetCookies')
For Each CookieString in Cookies using @FM
MatchCookieName = CookieString[1, 'F='][1, 'F '][1, 'F;']
If Name EQ MatchCookieName then
CookieNameFound = True$
end
Until CookieNameFound EQ True$
Next CookieValue
If CookieNameFound EQ True$ then
If IgnoreAttributes EQ True$ then
CookieString = Trim(CookieString[1, ';'])
end
Transfer CookieString to Cookie
end
end else
Error_Services('Add', 'The Name argument is missing in the ' : Service : ' service.')
end
Response = Cookie
end service
//----------------------------------------------------------------------------------------------------------------------
// SetResponseStatusCode
//
// Code - HTTP status code to set. - [Required]
//
// Sets the response status code generated by the most recent HTTP request.
//----------------------------------------------------------------------------------------------------------------------
Service SetResponseStatusCode(Code)
If Code NE '' then
ResponseStatusCode@ = Code
end else
Error_Services('Add', 'The Code argument is missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResponseStatusCode
//
// Gets the response status code generated by the most recent HTTP request.
//----------------------------------------------------------------------------------------------------------------------
Service GetResponseStatusCode()
Response = ResponseStatusCode@
end service
//----------------------------------------------------------------------------------------------------------------------
// SetResponseStatusPhrase
//
// Phrase - HTTP status phrase to set. - [Required]
//
// Sets the response status phrase generated by the most recent HTTP request.
//----------------------------------------------------------------------------------------------------------------------
Service SetResponseStatusPhrase(Phrase)
If Phrase NE '' then
ResponseStatusPhrase@ = Phrase
end else
Error_Services('Add', 'The Phrase argument is missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResponseStatusPhrase
//
// Gets the response status phrase generated by the most recent HTTP request.
//----------------------------------------------------------------------------------------------------------------------
Service GetResponseStatusPhrase()
Response = ResponseStatusPhrase@
end service
//----------------------------------------------------------------------------------------------------------------------
// SetResponseBody
//
// Body - The response body which would have been generated by an XMLHTTP call.
//
// Sets the response body generated by the most recent HTTP request.
//----------------------------------------------------------------------------------------------------------------------
Service SetResponseBody(Body)
ResponseBody@ = Body
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResponseBody
//
// Gets the response body generated by the most recent HTTP request.
//----------------------------------------------------------------------------------------------------------------------
Service GetResponseBody()
Response = ResponseBody@
end service
//----------------------------------------------------------------------------------------------------------------------
// SetTimeoutDuration
//
// TimeoutDuration - The length of time (in seconds) before an HTTP request will abort.
//
// Sets the timeout duration that will be used before an HTTP request will abort. This is only applicable if the
// request is asynchronous. If the timeout duration is empty, a default setting of 30 minutes (1800 seconds) will be
// set.
//----------------------------------------------------------------------------------------------------------------------
Service SetTimeoutDuration(TimeoutDuration)
If TimeoutDuration EQ '' then TimeoutDuration = 1800
TimeoutDuration@ = TimeoutDuration
end service
//----------------------------------------------------------------------------------------------------------------------
// GetTimeoutDuration
//
// Returns the timeout duration that will be used before an HTTP request will abort. This is only applicable if the
// request is asynchronous. If the timeout duration is empty, a default setting of 30 minutes (1800) seconds) will be
// returned.
//----------------------------------------------------------------------------------------------------------------------
Service GetTimeoutDuration()
If TimeoutDuration@ EQ '' then TimeoutDuration@ = 1800
Response = TimeoutDuration@
end service
//----------------------------------------------------------------------------------------------------------------------
// ClearResponseSettings
//
// Clears all of the global common variables used for responses.
//----------------------------------------------------------------------------------------------------------------------
Service ClearResponseSettings()
ResponseHeaderFields@ = ''
ResponseHeaderValues@ = ''
ResponseStatusCode@ = ''
ResponseStatusPhrase@ = ''
ResponseBody@ = ''
end service
//----------------------------------------------------------------------------------------------------------------------
// ClearRequestSettings
//
// Clears all of the global common variables used for requests.
//----------------------------------------------------------------------------------------------------------------------
Service ClearRequestSettings()
RequestHeaderFields@ = ''
RequestHeaderValues@ = ''
TimeoutDuration@ = 1800
end service

View File

@ -0,0 +1,38 @@
Subroutine HTTP_Aborted_Service(ProcErr)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Aborted_Service
Description : Handler program for the HTTP Aborted service module.
Notes : Service handler for HTTP Requests that get aborted either due to Runtime Errors or Status Errors.
If the Debugger Intercept has been enabled, this handler will only receive Status Error aborts.
Parameters :
ProcErr [in] -- The procedural error data being passed in from the OEngineServer. Unless otherwise
changed, the only reason this should be called is if there was a runtime error in one
of the stored procedures that was called by the initial request.
Metadata :
History : (Date, Initials, Notes)
02/27/17 dmb Original programmer. - [SRPFW-125]
03/04/17 dmb Replace direct logging with the CreateLogFile service. - [SRPFW-154]
12/03/18 dmb Update to use the SetResponseError service. - [SRPFW-257]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_INSERTS
// Generate a log file. Pass in the contents of the ProcErr argument as is.
HTTP_Services('CreateLogFile', 'Aborted', ProcErr)
HTTP_Services('SetResponseError', '', '', 500, ProcErr, FullEndpointURL)
Return

View File

@ -0,0 +1,553 @@
Function HTTP_Authentication_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Authentication_Services
Description : Handler program for all HTTP authentication.
Notes : Authentication techniques will vary depending upon the application so the code in the
AuthenticateRequest service will need to be customized as necessary.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
History : (Date, Initials, Notes)
02/25/15 dmb [SRPFW-91] Original programmer.
06/10/15 dmb [SRPFW-91] Add checks to make sure Username and Password are populated before attempting to
authenticate against the USERS table. This prevents easy authentication if the USERS table
isn't being managed well.
02/25/16 dmb [SRPFW-108] Add support for the GetEnableAuthenticateFlag service. If disabled, then automatically
authenticate the user.
02/25/16 dmb [SRPFW-108] Add support for the GetRealmValue service. Use this instead of hard-coding the
realm.
12/01/16 dmb Update the AuthenticateRequest service to verify authentication requirements of the current
URL using the URLRequiresAuthentication service.
07/01/17 dmb [SRPFW-184] Refactor using Enhanced BASIC+ syntax.
10/22/18 dmb [SRPFW-253] Add support for checking for whitelisted IPs in the AuthenticateRequest service.
10/31/18 dmb [SRPFW-254] Add GetWebAccountPassword, SetWebAccountPassword, and ValidateWebAccountPassword
services.
10/31/18 dmb [SRPFW-254] Update the AuthenticateRequest service to use the ValidateWebAccountPassword
service rather than relying upon a hardcoded USERS table.
11/01/18 dmb [SRPFW-256] Update NewPasswordTimeToLive$ equate to use the GetNewPasswordTimeToLive service
rather than the hardcoded value.
11/01/18 dmb [SRPFW-256] Update OldPasswordTimeToLive$ equate to use the GetOldPasswordTimeToLive service
rather than the hardcoded value.
11/09/18 dmb [SRPFW-256] Update ValidateWebAccountPassword service to implement the containment action if
too many failed password attempts have been attempted.
11/20/18 dmb [SRPFW-256] Add GetWebAccountEnabledStatus service. Update the AuthenticateRequest service
to use it before attempting to validate the password.
11/21/18 dmb [SRPFW-257] Add ResetWebAccountPassword service.
11/21/18 dmb [SRPFW-257] Update SetWebAccountPassword service to support a flag that ignores expiration
date.
11/23/18 dmb [SRPFW-257] Add SetAuthenticatedAccountID and GetAuthenticatedAccountID services.
12/12/18 dmb [SRPFW-257] Add SetAuthenticatedPassword and GetAuthenticatedPassword services.
06/24/19 dmb [SRPFW-276] Update the ValidateWebAccountPassword service to reset the invalid password
attempt counter for an account if a valid password is passed in.
12/09/19 dmb [SRPFW-296] Update all calls to Memory_Services to use a specific cache name.
06/30/20 dmb [SRPFW-313] Update the AuthenticateRequest service to return a 403 status code rather than
a 511 status code if the IP making the request is not permitted.
07/27/20 dmb [SRPFW-313] Replace references to the IPIsPermitted service with the IsIPPermitted service.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert SERVICE_SETUP
$insert HTTP_INSERTS
Equ SecondsPerHour$ to 60 * 60 ; // 60 minutes * 60 seconds = 3600
Equ SecondsPerDay$ to 24 * SecondsPerHour$ ; // 24 hours * 60 minutes * 60 seconds = 86400
Equ NewPasswordTimeToLive$ to HTTP_Services('GetNewPasswordTimeToLive') * SecondsPerHour$ ; // Convert hours to seconds
Equ OldPasswordTimeToLive$ to HTTP_Services('GetOldPasswordTimeToLive') * SecondsPerHour$ ; // Convert hours to seconds
Equ CacheName$ to 'SRPHTTPFramework'
Declare function Database_Services, RTI_CreateGUID
Declare subroutine Database_Services
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the HTTP Authentication services module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// AuthenticateRequest
//
// Returns a boolean value indicating the success of the authentication attempt. Default method is built around
// HTTP Basic Authentication.
//----------------------------------------------------------------------------------------------------------------------
Service AuthenticateRequest()
// All response headers that need to be set, regardless of authentication, should be handled here.
// 1. Access-Control-Allow-Origin must always be returned for CORS purposes.
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Origin', '*')
EnableAuthentication = HTTP_Services('GetEnableAuthenticationFlag')
FullEndPointURL = HTTP_Services('GetFullEndPointURL')
URLRequiresAuthentication = HTTP_Services('URLRequiresAuthentication', FullEndPointURL)
// Set the default status code and phrase if authentication fails.
StatusCode = 401
StatusPhrase = ''
If EnableAuthentication AND URLRequiresAuthentication then
HTTPMethod = HTTP_Services('GetHTTPRequestMethod')
HTTPRemoteAddr = HTTP_Services('GetHTTPRemoteAddr')
// Verify that the client IP is permitted. If there are no whitelisted IPs, then all IPs are permitted.
IsIPPermitted = HTTP_Services('IsIPPermitted', HTTPRemoteAddr)
If IsIPPermitted EQ True$ then
If HTTPMethod _EQC 'OPTIONS' then
// OPTIONS methods are never authenticated. Allow the user to be provisionally authenticated since the method
// will remains as OPTIONS throughout the entire API.
UserAuthenticated = True$
end else
// Assume the user is not authenticated until otherwise proven.
UserAuthenticated = False$
// The follow code provides a skeleton for support HTTP Basic authorization. This is a REST friendly
// authentication protocol and is documented in the core HTTP specification. Because REST does not preserve the
// state, all requests are authenticated regardless of previous authentication successes. HTTP Basic should
// only be used if https:// is being used. Otherwise, the credentials are being passed through as plain text.
// HTTP Basic uses the Authorization request header. However, the Authorization request header field does not
// always work with web server products when being passed to a third-party service. So, if the standard header
// returns nothing then check the custom X-Authorization request header.
AuthorizationB64 = HTTP_Services('GetRequestHeaderField', 'Authorization')
If AuthorizationB64 EQ '' then AuthorizationB64 = HTTP_Services('GetRequestHeaderField', 'X-Authorization')
If AuthorizationB64 NE '' then
// All HTTP Basic credentials should be Base64 encoded (in addition to encrypted via https://). Decode
// the credentials.
Authorization = SRP_Decode(AuthorizationB64[7, 999], 'BASE64')
// HTTP Basic credentials are always colon (:) delimited. Typically this will come through as
// Username:Password, but there could be other formats if the application requires it. For instance, for
// applications supporting multiple customers wherein each customer has their own group of users, the
// format could look like this CustomerID/Username:Password. This provides, in a sense, a three-part
// identifier. The following parsing logic would need to be adjusted as needed.
Username = Authorization[1, ':']
Password = Authorization[Col2() + 1, 999]
EnabledStatus = HTTP_Authentication_Services('GetWebAccountEnabledStatus', Username)
If EnabledStatus EQ True$ then
// Only authenticate if a username and password is provided. This prevents authenticating in the event
// the USERS row is missing a password or the USERS table has a blank row.
If (Username NE '') AND (Password NE '') then
// Below is where you would place your logic to validate the username, password, and any other credentials
// that were passed in. This code uses the default HTTP Framework WEB_ACCOUNTS table.
UserAuthenticated = HTTP_Authentication_Services('ValidateWebAccountPassword', Username, Password, False$)
// A successful login should set the WWW-Authenticate response header field with the appropriate value. The
// credentials are stored in memory so they can be retrieved by other services as needed.
If UserAuthenticated then
UserAuthenticated = True$
HTTP_Authentication_Services('SetAuthenticatedAccountID', Username)
HTTP_Authentication_Services('SetAuthenticatedPassword', Password)
// The realm attribute is a part of the HTTP authentication specification and is used to help identify all
// resources that belong to the same authentication. Typically this will be the same value for all requests
// within the same application. The branded name or OpenInsight name of the application would be a good
// example to use here.
Realm = HTTP_Services('GetRealmValue')
HTTP_Services('SetResponseHeaderField', 'WWW-Authenticate', 'xBasic realm="' : Realm : '"')
end
end
end else
// IP address making the request is not permitted. Do not authenticate the user.
StatusCode = 403
StatusPhrase = 'Account ' : Username : ' is disabled.'
UserAuthenticated = False$
end
end
end
end else
// IP address making the request is not permitted. Do not authenticate the user.
StatusCode = 403
StatusPhrase = HTTPRemoteAddr : ' is not a permitted IP address.'
UserAuthenticated = False$
end
end else
// Force the user to be authenticated since authentication is not enabled.
UserAuthenticated = True$
end
// Non-authenticated requests should have a 401 status code returned.
If Not(UserAuthenticated) then
HTTP_Services('SetResponseError', '', '', StatusCode, StatusPhrase, FullEndpointURL)
end
Response = UserAuthenticated
end service
//----------------------------------------------------------------------------------------------------------------------
// CleanUp
//
// Runs any clean up processes as needed to prepare the engine for the next request.
//----------------------------------------------------------------------------------------------------------------------
Service CleanUp()
// This service is called from HTTP_MCP before sending the response back to the caller. Any application specific
// logic that stores data in memory or attaches customer specific database tables should be properly closed out
// to avoid subsequent requests from having innappropriate access.
end service
//----------------------------------------------------------------------------------------------------------------------
// GetWebAccountEnabledStatus
//
// Gets the enabled status for the indicated web account.
//----------------------------------------------------------------------------------------------------------------------
Service GetWebAccountEnabledStatus(AccountID)
EnabledStatus = ''
If AccountID NE '' then
WebAccountRow = Database_Services('ReadDataRow', 'WEB_ACCOUNTS', AccountID)
If Error_Services('NoError') then
@DICT = Database_Services('GetTableHandle', 'DICT.WEB_ACCOUNTS')
@ID = AccountID
@RECORD = WebAccountRow
EnabledStatus = {ACCOUNT_ENABLED}
If EnabledStatus NE True$ then EnabledStatus = False$ ; // Always default to disabled unless explicitly enabled.
end
end else
Error_Services('Add', 'AccountID argument was missing in the ' : Service : ' service.')
end
Response = EnabledStatus
end service
//----------------------------------------------------------------------------------------------------------------------
// GetWebAccountPassword
//
// Gets the current password for the indicated web account. If the CreateIfNew flag is set to True$, a new password will
// be generated if no password currently exists. This new password will be added to the web account.
//----------------------------------------------------------------------------------------------------------------------
Service GetWebAccountPassword(AccountID, CreateIfNew)
Password = ''
If CreateIfNew NE True$ then CreateIfNew = False$
If AccountID NE '' then
WebAccountRow = Database_Services('ReadDataRow', 'WEB_ACCOUNTS', AccountID)
If Error_Services('NoError') then
@DICT = Database_Services('GetTableHandle', 'DICT.WEB_ACCOUNTS')
@ID = AccountID
@RECORD = WebAccountRow
Begin Case
Case ({CURRENT_PASSWORD} EQ '') AND (CreateIfNew EQ True$)
Password = HTTP_Authentication_Services('ResetWebAccountPassword', AccountID, CurrentPassword)
Case ({CURRENT_PASSWORD} EQ '') AND (CreateIfNew EQ False$)
Error_Services('Add', 'No password exists for Account ID ' : AccountID)
Case Otherwise$
Password = {CURRENT_PASSWORD}
End Case
end
end else
Error_Services('Add', 'AccountID argument was missing in the ' : Service : ' service.')
end
Response = Password
end service
//----------------------------------------------------------------------------------------------------------------------
// ResetWebAccountPassword
//
// Resets the current password (or creates a new one) for the indicated web account. This new password will be added to
// the web account.
//----------------------------------------------------------------------------------------------------------------------
Service ResetWebAccountPassword(AccountID, CurrentPassword)
Password = ''
If AccountID NE '' then
WebAccountRow = Database_Services('ReadDataRow', 'WEB_ACCOUNTS', AccountID)
If Error_Services('NoError') then
@DICT = Database_Services('GetTableHandle', 'DICT.WEB_ACCOUNTS')
@ID = AccountID
@RECORD = WebAccountRow
// Password is based on a random GUID and then encoded as Base64.
Password = RTI_CreateGUID('B')
HTTP_Authentication_Services('SetWebAccountPassword', AccountID, CurrentPassword, Password, True$)
If Error_Services('HasError') then Password = ''
end
end else
Error_Services('Add', 'AccountID argument was missing in the ' : Service : ' service.')
end
Response = Password
end service
//----------------------------------------------------------------------------------------------------------------------
// ValidateWebAccountPassword
//
// Validates the password for the indicated web account. If the CurrentOnly argument is set to True$, then only the
// current password associated with the web account will be validated. Otherwise, the old password will also be valided
// using the expiration date and time associated.
//----------------------------------------------------------------------------------------------------------------------
Service ValidateWebAccountPassword(AccountID, Password, CurrentOnly)
Valid = False$ ; // Assume False$ for now.
ErrorMessage = ''
If CurrentOnly NE True$ then CurrentOnly = False$
If (AccountID NE '') AND (Password NE '') then
WebAccountRow = Database_Services('ReadDataRow', 'WEB_ACCOUNTS', AccountID)
If Error_Services('NoError') then
@DICT = Database_Services('GetTableHandle', 'DICT.WEB_ACCOUNTS')
@ID = AccountID
@RECORD = WebAccountRow
ThisSeconds = Date() * SecondsPerDay$ + Time()
Begin Case
Case Password EQ {CURRENT_PASSWORD}
ExpireSeconds = {CURRENT_PASSWORD_EXPIRE_DATE} * SecondsPerDay$ + {CURRENT_PASSWORD_EXPIRE_TIME}
If ThisSeconds LE ExpireSeconds then
Valid = True$
end else
ErrorMessage = 'Password is expired. A new one needs to be requested.'
end
Case (Password EQ {OLD_PASSWORD}) AND (CurrentOnly EQ False$)
ExpireSeconds = {OLD_PASSWORD_EXPIRE_DATE} * SecondsPerDay$ + {OLD_PASSWORD_EXPIRE_TIME}
If ThisSeconds LE ExpireSeconds then
Valid = True$
end else
ErrorMessage = 'Password is expired. A new one needs to be requested.'
end
Case Otherwise$
ErrorMessage = 'Password is invalid.'
End Case
If ErrorMessage EQ '' then
// Reset the number of invalid password attempts for the account.
{INVALID_PASSWORD_ATTEMPTS} = 0
Database_Services('WriteDataRow', 'WEB_ACCOUNTS', @ID, @RECORD, True$, False$, True$)
end else
// Update the total invalid password attempts for this server.
Attempts = HTTP_Services('GetTotalInvalidPasswordAttempts')
Attempts += 1
HTTP_Services('SetTotalInvalidPasswordAttempts', Attempts)
// Update the total invalid password attempts for this account.
InvalidPasswordAttempts = {INVALID_PASSWORD_ATTEMPTS} + 1
{INVALID_PASSWORD_ATTEMPTS} = InvalidPasswordAttempts
Database_Services('WriteDataRow', 'WEB_ACCOUNTS', @ID, @RECORD, True$, False$, True$)
InvalidPasswordLimit = HTTP_Services('GetInvalidPasswordLimit')
If InvalidPasswordAttempts GE InvalidPasswordLimit then
ContainmentAction = HTTP_Services('GetContainmentAction')
Begin Case
Case ContainmentAction _EQC 'Disable Server'
HTTP_Services('SetServerEnabled', False$)
Case ContainmentAction _EQC 'Quarantine Account'
{ACCOUNT_ENABLED} = False$
WebAccountRow = @RECORD
Database_Services('WriteDataRow', 'WEB_ACCOUNTS', AccountID, WebAccountRow, True$, False$, True$)
End Case
ActionDetails = ''
ActionDetails<1> = Fmt('Containment Action:', 'L#35') : ContainmentAction
ActionDetails<2> = Fmt('Invalid Password Limit:', 'L#35') : InvalidPasswordLimit
ActionDetails<3> = Fmt('Total Invalid Password Attempts:', 'L#35') : Attempts
ActionDetails<4> = Fmt('Account ID:', 'L#35') : AccountID
ActionDetails<5> = Fmt('Total Account Invalid Attempts:', 'L#35') : InvalidPasswordAttempts
HTTP_Authentication_Services('ContainmentActionNotification', ActionDetails)
end
Error_Services('Add', ErrorMessage)
end
end
end else
Error_Services('Add', 'AccountID or Password argument was missing in the ' : Service : ' service.')
end
Response = Valid
end service
//----------------------------------------------------------------------------------------------------------------------
// SetWebAccountPassword
//
// Sets a new password for the indicated web account. If no current password already exists, then the new password will
// be added to the web account automatically. Otherwise, the current password will be verified before allowing a new
// password to be set.
//----------------------------------------------------------------------------------------------------------------------
Service SetWebAccountPassword(AccountID, CurrentPassword, NewPassword, OverrideExpireDate)
If OverrideExpireDate NE True$ then OverrideExpireDate = False$
If (AccountID NE '') AND (NewPassword NE '') then
WebAccountRow = Database_Services('ReadDataRow', 'WEB_ACCOUNTS', AccountID)
If Error_Services('NoError') then
@DICT = Database_Services('GetTableHandle', 'DICT.WEB_ACCOUNTS')
@ID = AccountID
@RECORD = WebAccountRow
If {CURRENT_PASSWORD} EQ '' then
// This is a new password for this web account. Accept the new password.
CreateDate = Date()
CreateTime = Time()
CreateSeconds = CreateDate * SecondsPerDay$ + CreateTime
ExpireSeconds = CreateSeconds + NewPasswordTimeToLive$
ExpireDate = Int(ExpireSeconds / SecondsPerDay$)
ExpireTime = Mod(ExpireSeconds, SecondsPerDay$)
{CURRENT_PASSWORD} = NewPassword
{CURRENT_PASSWORD_CREATE_DATE} = CreateDate
{CURRENT_PASSWORD_CREATE_TIME} = CreateTime
{CURRENT_PASSWORD_EXPIRE_DATE} = ExpireDate
{CURRENT_PASSWORD_EXPIRE_TIME} = ExpireTime
WebAccountRow = @RECORD
Database_Services('WriteDataRow', 'WEB_ACCOUNTS', AccountID, WebAccountRow, True$, False$, True$)
end else
// A current password already exists.
Valid = HTTP_Authentication_Services('ValidateWebAccountPassword', AccountID, CurrentPassword, True$) OR (OverrideExpireDate EQ True$)
If Valid EQ True$ then
Begin Case
Case CurrentPassword EQ NewPassword
// New password must be different than the current password.
Error_Services('Add', 'New password must be different than the current password.')
Case Otherwise$
// Current password is valid and new password is different.
// Make the current password the old passowrd. Reset the expiration date and time as
// needed.
CurrentPassword = {CURRENT_PASSWORD}
CurrentPasswordCreateDate = {CURRENT_PASSWORD_CREATE_DATE}
CurrentPasswordCreateTime = {CURRENT_PASSWORD_CREATE_TIME}
{OLD_PASSWORD} = CurrentPassword
{OLD_PASSWORD_CREATE_DATE} = CurrentPasswordCreateDate
{OLD_PASSWORD_CREATE_TIME} = CurrentPasswordCreateTime
ThisSeconds = Date() * SecondsPerDay$ + Time()
ExpireSeconds = ThisSeconds + OldPasswordTimeToLive$
ExpireDate = Int(ExpireSeconds / SecondsPerDay$)
ExpireTime = Mod(ExpireSeconds, SecondsPerDay$)
{OLD_PASSWORD_EXPIRE_DATE} = ExpireDate
{OLD_PASSWORD_EXPIRE_TIME} = ExpireTime
// Set the new password information.
CreateDate = Date()
CreateTime = Time()
CreateSeconds = CreateDate * SecondsPerDay$ + CreateTime
ExpireSeconds = CreateSeconds + NewPasswordTimeToLive$
ExpireDate = Int(ExpireSeconds / SecondsPerDay$)
ExpireTime = Mod(ExpireSeconds, SecondsPerDay$)
{CURRENT_PASSWORD} = NewPassword
{CURRENT_PASSWORD_CREATE_DATE} = CreateDate
{CURRENT_PASSWORD_CREATE_TIME} = CreateTime
{CURRENT_PASSWORD_EXPIRE_DATE} = ExpireDate
{CURRENT_PASSWORD_EXPIRE_TIME} = ExpireTime
WebAccountRow = @RECORD
Database_Services('WriteDataRow', 'WEB_ACCOUNTS', AccountID, WebAccountRow, True$, False$, True$)
End Case
end
end
end
end else
Error_Services('Add', 'AccountID or NewPassword argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetAuthenticatedAccountID
//
// Sets the account ID that was successfully authenticated for this request.
//----------------------------------------------------------------------------------------------------------------------
Service SetAuthenticatedAccountID(AccountID)
If AccountID NE '' then
Memory_Services('SetValue', ServiceModule : '*AuthenticatedAccountID', AccountID, CacheName$)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetAuthenticatedAccountID
//
// Gets the successfully authenticated account ID for this request.
//----------------------------------------------------------------------------------------------------------------------
Service GetAuthenticatedAccountID()
AccountID = Memory_Services('GetValue', ServiceModule : '*AuthenticatedAccountID', '', '', CacheName$)
Response = AccountID
end service
//----------------------------------------------------------------------------------------------------------------------
// SetAuthenticatedPassword
//
// Sets the password that was successfully authenticated for this request.
//----------------------------------------------------------------------------------------------------------------------
Service SetAuthenticatedPassword(Password)
If Password NE '' then
Memory_Services('SetValue', ServiceModule : '*AuthenticatedPassword', Password, CacheName$)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetAuthenticatedPassword
//
// Gets the successfully authenticated password for this request.
//----------------------------------------------------------------------------------------------------------------------
Service GetAuthenticatedPassword()
Password = Memory_Services('GetValue', ServiceModule : '*AuthenticatedPassword', '', '', CacheName$)
Response = Password
end service
//----------------------------------------------------------------------------------------------------------------------
// ContainmentActionNotification
//
// Handles notification protocols when a containment breach has occured. This handler is mostly a placeholder for
// developers to add their own custom protocol action.
//----------------------------------------------------------------------------------------------------------------------
Service ContainmentActionNotification(ActionDetails)
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,535 @@
Function HTTP_Contacts_Services(RemainingURL)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Contacts_Services
Description : Handler program for the HTTP Contacts service module.
Notes : In the comments below, the term "resource" will be used. In most cases this is synonymous with a
database row, but the web (and especially REST) abstracts all information being returned simply as a
"resource". This provides developers more flexibility in their web API designs. For instance, a
resource can be a combination of various different database rows and other data (like images,
documents, etc.)
In this sample service, the "contact" resource will closely map to a sample CONTACTS database table.
This is meant to provide the OpenInsight web API developer an easy way to create a web-based CRUD
API that can also be extended as needed. Locking is performed on the resource at the database row
level using the Lock statement, but this is only done just prior to the Write statement since HTTP
is a stateless protocol. While some attempts to wait for the lock to be available could be added,
this is normally discouraged since this could cause the HTTP request to take too long to finish.
All HTTP web services should include the HTTP_SERVICE_SETUP insert. This will provide several useful
variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
SelfURL - The URL path representing the current service.
FullEndPointURL - The URL submitted by the client. This can be the same or longer than
the SelfURL.
NextSegment - The URL segment immediately following the SelfURL (if any). This
could contain the name of the next service or it could contain the
Item ID for the current service (aka resource).
CurrentServiceHandler - The name of this stored procedure.
Parameters :
RemainingURL [in] -- The remaining portion of the URL that follows the URL that launched this current
service. This information is used in the HTTP_SERVICE_SETUP insert to populate other
useful variables (see Notes above).
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
04/17/15 dmb Original programmer. - [SRPFW-96]
03/09/16 dmb Refactor to use the updated RunHTTPService service. - [SRPFW-112]
07/01/17 dmb Refactor using Enhanced BASIC+ syntax. - [SRPFW-184]
07/07/17 dmb Add support for PUT and PATCH so this routine can serve as a more complete CRUD example.
- [SRPFW-187]
07/08/17 dmb Remove checks for query parameters from the main router and make this a function of the
GET method/URL handler. - [SRPFW-187]
07/19/18 dmb Fix minor typo in the NextSegment variable in the GetItem method. - [SRPFW-248]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_SERVICE_SETUP
$insert HTTP_INSERTS
// In the comments related to URL examples, words surrounded by "{" and "}" represent the names of values that
// will appear in the actual URL. Words surrounded by "<" and ">" represent variables that contain values relevant to
// the actual URL. See the Notes above for a list of the most important variables.
//
// For instance, <APIURL>/contacts/{KeyID} could look like https://api.mysite.com/v1/contacts/1000, assuming <APIURL>
// resolves to "https://api.mysite.com/v1" and {KeyID} resolves to "1000".
//
// The type of request being made needs to be determined based on the URL content. There are only a few possibilities
// that this API will support:
//
// All Resources = <APIURL>/contacts
// Specific Resource = <APIURL>/contacts/{KeyID}
// Specific Resource Property = <APIURL>/contacts/{KeyID}/{property}
//
// Also, any URL can end with query parameters like this:
//
// Resource Query = <APIURL>/contacts?{property}={value}
//
// The request will go to the same handler as if the query parameters were missing but that handler itself will
// determine if the query parameters will be used or ignored.
// Assume the current HTTP method is valid until proven otherwise.
ValidMethod = True$
// Assume the current web service is valid until provent otherwise.
ValidService = True$
// Assume no HTTP methods are valid until proven otherwise.
AllowedMethods = ''
// A list of all services able to be called from this URL.
AllowedServices = 'picture'
// Handle the HTTP request as needed.
Begin Case
Case RemainingURL _EQC ''
// This means the URL ends with /contacts, which means this is the end point. The HTTP methods roughly function
// as follows:
//
// POST - Creates a new resource. Assumes the server will generate the Key ID, which will be returned in the
// HTTP response.
// GET - The client is requesting a collection of all contacts.
AllowedMethods = 'POST,GET,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub Post, Get, Options
end else
ValidMethod = False$
end
Case Count(RemainingURL, '/') EQ 0
// This means the URL ends with /contacts/{KeyID}. {KeyID} is also known as the resource ID. When a resource is
// closely mapped to a database row (as is the case with this Contacts API), this is where the basic CRUD
// functionality will be added. The HTTP methods roughly function as follows:
//
// PUT - Creates* a resource using the Key ID contained in the URL. This is equivalent to the Write
// statement in BASIC+.
// GET - Reads the resource referenced by the Key ID contained in the URL. This is equivalent to the Read
// statement in BASIC+.
// PUT - Updates* the resource referenced by the Key ID contained in the URL. This is the exact same
// feature defined above. This should make sense since the Write statement in BASIC+ is used to
// create and update database rows. Note, the PUT method assumes the entire resource is within the
// request body, not just the changes. See the PATCH method below.
// DELETE - Deletes the source referenced by the Key ID contained in the URL. This is equivalent to the Delete
// statement in BASIC+.
//
// * Many people use the POST method for creating (and updating) a resource. However, per the HTTP
// specification, POST is to be used when creating a new resource that does not yet have a resource ID
// (i.e., Key ID). The server determines the Key ID and this is returned to the client for future use.
//
// PATCH - Updates specific properties (e.g., data columns) of the resource referenced by the Key ID
// contained in the URL. This is similar in concept to the WriteV statement in BASIC+, although
// multiple changes in the resource can be updated with one PATCH method.
AllowedMethods = 'PUT,GET,DELETE,PATCH,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub PutItem, GetItem, DeleteItem, PatchItem, OptionsItem
end else
ValidMethod = False$
end
Case Count(RemainingURL, '/') GE 1
// This means the URL ends with /contacts/{KeyID}/{property}. A property can be any specific data that is
// associated with the resource. It could be a column value, an image, a PDF document, etc. In this case, the
// only property supported by this web API is the contact's "picture". The developer can put add code in this
// service to update the picture or the developer can create another HTTP service to handle this. Since a
// "picture" service might be useful as a property for other types of resources, a call to a dedicated "picture"
// HTTP service will be made "as is" so it can handle the request. Calling another HTTP service is similar to
// the way one MFS calls another MFS by modifying the FS list. In this case, the NextSegment and RemainingURL
// variables will need to be modified.
Property = FullEndPointURL[-1, 'B/']
Locate Property in AllowedServices using ',' setting ServicePos then
NextSegment = Property ; // This allows the RunHTTPService to call HTTP_PICTURE_SERVICES.
RemainingURL = '' ; // This variable won't be used in the HTTP_PICTURE_SERVICES code, but to keep the
; // variables well formed, this should be cleared.
HTTP_Services('RunHTTPService', NextSegment, RemainingURL)
end else
ValidService = False$
end
Case Otherwise$
ValidService = False$
End Case
// Resolve any invalid conditions with the HTTP request.
Begin Case
Case Not(ValidService)
HTTP_Services('SetResponseStatus', 404, NextSegment : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
Case Not(ValidMethod)
HTTP_Services('SetResponseStatus', 405, HTTPMethod : ' is not valid for this service.')
GoSub SetAllowedMethods
End Case
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Web Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// Post
//
// Attempts to create a new resource. Creating a new which is a database row follows these guidelines:
//
// - Any unexpected system errors will return a 500 status code (Internal Server Error).
// - If no errors occur then a 201 (Created) status code is returned. The Content-Location response header will be
// set to the value of the URL that will allow the client to GET the newly created resource.
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
//----------------------------------------------------------------------------------------------------------------------
Post:
HTTP_Resource_Services('PostDatabaseItem', 'CONTACTS', SelfURL)
return
//----------------------------------------------------------------------------------------------------------------------
// Get
//
// Returns a collection of resources.
//
// The easiest way to return a list of resources that are mapped to a database table is to use the GetDatabaseItems
// service. This is being done in the code below. This URL also supports the passing in of query parameters, which in
// this case will be used to return those items that match the property/value query.
//
// A property can be any specific data that is associated with the resource. It could be a column value, an image, a PDF
// document, etc. In this case, only properties that match the name of database columns in the CONTACTS table will be
// supported by this web API. Note, developers can limit the properties (aka columns) to those that are indexed in order
// to avoid having a request take too long.
//----------------------------------------------------------------------------------------------------------------------
Get:
HAL = '' ; // Initialize the response.
If HTTP_Services('GetHTTPGetString') NE '' then
// This means the URL ends with /contacts?{property}={value}. The client is searching for one or more contacts
// that match the query parameters. This is equivalent to doing a filtered RLIST search.
// Get the query string passed into the URL.
GetString = HTTP_Services('GetHTTPGetString')
// Get the name of the property being queried.
Property = GetString[1, 'F=']
// Get the value being searched for.
Value = HTTP_Services('GetQueryField', Property)
// Get the database columns for the table.
ColumnNames = HTTP_Resource_Services('GetColumnNames', 'CONTACTS')
ColumnName = Property
Convert @Lower_Case to @Upper_Case in ColumnName
// Verify the property matches a valid column in the table.
Locate ColumnName in ColumnNames using @FM setting fPos then
// Use the GetDatabaseItems service to perform the search and prepare the HAL+JSON response. If a more complex
// or optimized solution is needed, then replace the following with custom code.
Filter = 'SELECT CONTACTS WITH ' : ColumnName : ' CONTAINING ' : Quote(Value)
// The GetDatabaseItems service will return all database column values unless otherwise specified. Since a query
// search might generated several results, it is sometimes best to pass in just those columns that are important
// for the query result.
ColumnNames = 'first_name' : @FM : 'last_name' : @FM : 'email'
Locate ColumnName in ColumnNames using @FM setting fPos else
// Make sure the property being searched is included in the columns being returned.
ColumnNames := @FM : Property
end
HAL = HTTP_Resource_Services('GetDatabaseItems', Filter, 'CONTACTS', SelfURL, ColumnNames)
end else
// This is not a valid property, which means the URL does not resolve. Set a 404 error. Add a description if
// desired.
HTTP_Services('SetResponseStatus', 404)
end
end else
// This means the URL ends with /contacts. The client is requesting all resources available at this URL.
// This is equivalent to performing an unfiltered SELECT statement. The ColumnNames argument for the
// GetDatabaseItems service specifies which values should be represented in the JSON response.
Filter = ''
ColumnNames = 'first_name' : @FM : 'last_name' : @FM : 'email'
HAL = HTTP_Resource_Services('GetDatabaseItems', Filter, 'CONTACTS', SelfURL, ColumnNames)
end
Response = HAL
return
//----------------------------------------------------------------------------------------------------------------------
// Options
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
Options:
GoSub SetCommonOptionResponseHeaders
return
//----------------------------------------------------------------------------------------------------------------------
// PutItem
//
// Attempts to update the resource. If the resource does not already exist then a new one will be created. Updating a
// resource which is a database row follows these guidelines:
//
// - Any unexpected system errors will return a 500 status code (Internal Server Error).
// - If no errors occur then a 200 (OK) status code is returned if the resource previously existed. Otherwise,
// a 201 (Created) status code is returned and the Content-Location response header will be set to the value of the
// URL that will allow the client to GET a newly created resource.
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
//----------------------------------------------------------------------------------------------------------------------
PutItem:
KeyID = NextSegment
HTTP_Resource_Services('PutDatabaseItem', 'CONTACTS', SelfURL : '/' : KeyID, KeyID)
return
//----------------------------------------------------------------------------------------------------------------------
// GetItem
//
// Returns the specific resource.
//
// The easiest way to return a resource that is mapped to a database row is to use the GetDatabaseItem service. This
// is being done in the code below. However, to demonstrate how then basic functionality can be extended, there is
// additional code below that will show how to add the Contact resource's image URL to the JSON response.
//----------------------------------------------------------------------------------------------------------------------
GetItem:
KeyID = NextSegment
// Calling this service alone would be sufficient to return a HAL+JSON representation of the specified contact.
HAL = HTTP_Resource_Services('GetDatabaseItem', 'CONTACTS', SelfURL : '/' : KeyID, KeyID)
// Since the Contact resource can also have an image, the following code will generate a valid URL for this image
// in case the client wants to retrieve it. The URL will then be added to the HAL+JSON response so this comes
// back as a single representation of the resource.
If HAL NE '' then
// Make the JSON content an object so the SRP_JSON API can work with it.
ParseResponse = SRP_JSON(HALRootObj, 'PARSE', HAL)
If ParseResponse EQ '' then
// The CONTACTS table has a PICTURE data column. This stores the physical path to the image, but this is
// not useful to the HTTP client. Create a URL that will allow the client to retrieve the image.
PictureValue = SRP_JSON(HALRootObj, 'GETVALUE', 'picture', '')
If PictureValue NE '' then
If SRP_JSON(PictureObj, 'NEW', 'OBJECT') then
// Create the URL and add it to the JSON object.
ImageURL = SelfURL : '/' : KeyID : '/picture'
SRP_JSON(PictureObj, 'SETVALUE', 'href', ImageURL)
SRP_JSON(PictureObj, 'SETVALUE', 'name', 'picture-' : KeyID)
SRP_JSON(HALRootObj, 'SET', 'picture', PictureObj)
HAL = SRP_JSON(HALRootObj, 'STRINGIFY', 'STYLED')
// Set the HTTP response body with the final HAL+JSON results.
HTTP_Services('SetResponseBody', HAL, False$, 'application/hal+json')
SRP_JSON(PictureObj, 'RELEASE')
end
end
SRP_JSON(HALRootObj, 'RELEASE')
end
end
Response = HAL
return
//----------------------------------------------------------------------------------------------------------------------
// DeleteItem
//
// Attempts to delete the resource. Deleting a resource which is a database row follows these guidelines:
//
// - Any unexpected system errors will return a 500 status code (Internal Server Error).
// - If no errors occur then a 204 (No Content) status code is returned.
// - If the resource was already deleted then a 204 (No Content) status code is returned.
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
//----------------------------------------------------------------------------------------------------------------------
DeleteItem:
KeyID = NextSegment
HTTP_Resource_Services('DeleteDatabaseItem', 'CONTACTS', KeyID)
return
//----------------------------------------------------------------------------------------------------------------------
// PatchItem
//
// Attempts to update the resource. Updating a resource which is a database row follows these guidelines:
//
// - Any unexpected system errors will return a 500 status code (Internal Server Error).
// - If no errors occur then a 200 (OK) status code is returned.
// - If the resource is new then a 404 (Not Found) status code is returned. PATCH only works with existing resources.
// - Only those properties (columns) which are passed in will get updated.
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
//----------------------------------------------------------------------------------------------------------------------
PatchItem:
KeyID = NextSegment
HTTP_Resource_Services('PatchDatabaseItem', 'CONTACTS', SelfURL : '/' : KeyID, KeyID)
return
//----------------------------------------------------------------------------------------------------------------------
// OptionsItem
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
OptionsItem:
GoSub SetCommonOptionResponseHeaders
return
//----------------------------------------------------------------------------------------------------------------------
// PutItemProperty
//
// Attempts to update the property of a specific resource.
//
// A property can be any specific data that is associated with the resource. It could be a column value, an image, a PDF
// document, etc. In this case, the only property supported by this web API is the contact's "picture". The developer
// can put add code here to update the picture or the developer can create another HTTP service to handle this. Since a
// "picture" service might be useful as a property for other types of resources, a call to a dedicated "picture" HTTP
// service will be made.
//
// Calling another HTTP service is similar to the way one MFS calls another MFS by modifying the FS list. In this case,
// the NextSegment and RemainingURL variables will need to be modified. At this point in the stack the following
// API variables look like this:
//
// HTTPMethod : PUT
// SelfURL : <APIURL>/contacts
// NextSegment : {KeyID}
// FullEndPointURL : <APIURL>/contacts/{KeyID}/{property}
//
// The code will need to determine if a supported property has been passed in. If so, then the next HTTP service will
// need to be called with the appropriate modifications to the variables.
//----------------------------------------------------------------------------------------------------------------------
PutItemProperty:
// Get the name of the property by looking at the last segment in the FullEndPointURL variable. An assumption is
// being made that there are no other segments in the URL that follow the property name.
Property = FullEndPointURL[-1, 'B/']
Locate Property in AllowedServices using ',' setting ServicePos then
// A supported property has been passed in the URL. Modify the NextSegment and RemainingURL variables so the
// next HTTP service can be called correctly.
NextSegment = Property ; // This allows the RunHTTPService to call HTTP_PICTURE_SERVICES.
RemainingURL = '' ; // This variable won't be used in the HTTP_PICTURE_SERVICES code, but to keep the
; // variables well formed, this should be cleared.
HTTP_Services('RunHTTPService', NextSegment, RemainingURL)
end else
// The URL contains an unsupported property. Return a 404 error.
HTTP_Services('SetResponseStatus', 404, Property : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// GetItemProperty
//
// Returns the property of a specific resource.
//
// A property can be any specific data that is associated with the resource. It could be a column value, an image, a PDF
// document, etc. In this case, the only property supported by this web API is the contact's "picture". The developer
// can put add code here to return the picture or the developer can create another HTTP service to handle this. Since a
// "picture" service might be useful as a property for other types of resources, a call to a dedicated "picture" HTTP
// service will be made.
//
// Calling another HTTP service is similar to the way one MFS calls another MFS by modifying the FS list. In this case,
// the NextSegment and RemainingURL variables will need to be modified. At this point in the stack the following
// API variables look like this:
//
// HTTPMethod : GET
// SelfURL : <APIURL>/contacts
// NextSegment : {KeyID}
// FullEndPointURL : <APIURL>/contacts/{KeyID}/{property}
//
// The code will need to determine if a supported property has been passed in. If so, then the next HTTP service will
// need to be called with the appropriate modifications to the variables.
//----------------------------------------------------------------------------------------------------------------------
GetItemProperty:
// Get the name of the property by looking at the last segment in the FullEndPointURL variable. An assumption is
// being made that there are no other segments in the URL that follow the property name.
Property = FullEndPointURL[-1, 'B/']
If Property _EQC 'picture' then
// A supported property has been passed in the URL. Modify the NextSegment and RemainingURL variables so the
// next HTTP service can be called correctly.
NextSegment = Property ; // This allows the RunHTTPService to call HTTP_PICTURE_SERVICES.
RemainingURL = '' ; // This variable won't be used in the HTTP_PICTURE_SERVICES code, but to keep the
; // variables well formed, this should be cleared.
HTTP_Services('RunHTTPService', NextSegment, RemainingURL)
end else
// The URL contains an unsupported property. Return a 404 error.
HTTP_Services('SetResponseStatus', 404, Property : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// OptionsItemProperty
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
OptionsItemProperty:
GoSub SetCommonOptionResponseHeaders
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SetCommonOptionResponseHeaders
//
// Sets the response headers that will be common for all OPTIONS methods.
//----------------------------------------------------------------------------------------------------------------------
SetCommonOptionResponseHeaders:
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'x-authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Max-Age', 1728000)
GoSub SetAllowedMethods
return
//----------------------------------------------------------------------------------------------------------------------
// SetAllowedMethods
//
// Sets the Allow response header field as appropriate for the requested URL.
//----------------------------------------------------------------------------------------------------------------------
SetAllowedMethods:
If AllowedMethods NE '' then
For Each Method in AllowedMethods using ','
HTTP_Services('SetResponseHeaderField', 'Allow', Method, True$)
Next Method
end
return

View File

@ -0,0 +1,31 @@
Subroutine HTTP_Debugger_Service(Void)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Debugger_Service
Description : Handler program for the HTTP Debugger service module.
Notes : Service handler for HTTP Requests that abort due to a Runtime Error and the Debugger Intercept
has been enabled.
Parameters :
Metadata :
History : (Date, Initials, Notes)
03/07/17 dmb Original programmer. - [SRPFW-155]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_INSERTS
$insert RTI_DEBUG_COMMON
HTTP_Services('CreateLogFile', 'Debugger', SPStatus@ : @RM : SPStatCode@ : @RM : Curr_Program@ : @RM : CallDepth@ : @RM : LineNo@ : @RM : CallStack@)
Return

View File

@ -0,0 +1,199 @@
Function HTTP_Entry_Point_Services(RemainingURL)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Entry_Point_Services
Description : Handler program for the HTTP Entry Point service module.
Notes : All HTTP web services should include the HTTP_SERVICE_SETUP insert. This will provide several useful
variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
SelfURL - The URL path representing the current service.
FullEndPointURL - The URL submitted by the client. This can be the same or longer than
the SelfURL.
NextSegment - The URL segment immediately following the SelfURL (if any). This
could contain the name of the next service or it could contain the
Item ID for the current service (aka resource).
CurrentServiceHandler - The name of this stored procedure.
Parameters :
RemainingURL [in] -- The remaining portion of the URL that follows the URL that launched this current
service. This information is used in the HTTP_SERVICE_SETUP insert to populate other
useful variables (see Notes above).
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
02/04/15 dmb Original programmer. - [SRPFW-92]
04/17/15 dmb Replace the SetHALLinks service with SetHALCollection service for the Get method. -
[SRPFW-92]
03/09/16 dmb Refactor to use the updated RunHTTPService service. - [SRPFW-112]
07/01/17 dmb Refactor using Enhanced BASIC+ syntax. - [SRPFW-184]
07/10/17 dmb Add version to the list of allowed services. - [SRPFW-188]
09/13/18 dmb Add scan as an allowed service. Remove contacts and version.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_SERVICE_SETUP
$insert HTTP_INSERTS
// Assume the current HTTP method is valid until proven otherwise.
ValidMethod = True$
// Assume the current web service is valid until provent otherwise.
ValidService = True$
// Assume no HTTP methods are valid until proven otherwise.
AllowedMethods = ''
// A list of all services able to be called from this URL.
AllowedServices = 'scan'
// Since all authenticated API requests will start with the Entry Point, any authentication-dependent global response
// headers should be set here.
GoSub SetGlobalResponseHeaders
// Handle the HTTP request as needed.
Begin Case
Case RemainingURL _EQC ''
// This means the URL matches the <APIURL>, which means this is the entry point. The client is requesting a
// collection of services available.
AllowedMethods = 'GET,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub Get, Options
end else
ValidMethod = False$
end
Case Count(RemainingURL, '/') GE 0
// This means the URL ends with /{service}, where <NextSegment> is the name of the service. The client is
// requesting a specific web service. If this is an allowed service, just call the service "as is" and let it
// handle the request. Calling another HTTP service is similar to the way one MFS calls another MFS by modifying
// the FS list. In this case, the NextSegment and RemainingURL variables will need to be modified.
Locate NextSegment in AllowedServices using ',' setting ServicePos then
RemainingURL = Field(RemainingURL, '/', 2, 99)
HTTP_Services('RunHTTPService', NextSegment, RemainingURL)
end else
ValidService = False$
end
Case Otherwise$
ValidService = False$
End Case
// Resolve any invalid conditions with the HTTP request.
Begin Case
Case Not(ValidService)
HTTP_Services('SetResponseStatus', 404, NextSegment : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
Case Not(ValidMethod)
HTTP_Services('SetResponseStatus', 405, HTTPMethod : ' is not valid for this service.')
GoSub SetAllowedMethods
End Case
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Web Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// Get
//
// Returns the available services.
//----------------------------------------------------------------------------------------------------------------------
Get:
HREFNames = ''
HREFURIs = ''
For Each Service in AllowedServices using ','
HREFNames := service : @FM
HREFURIs := SelfURL : '/' : Service : @FM
Next Service
HREFNames[-1, 1] = ''
HREFURIs[-1, 1] = ''
HTTP_JSON_Services('SetHALCollection', SelfURL, HREFURIs, HREFNames)
If Error_Services('NoError') then
Services = HTTP_JSON_Services('GetHAL')
HTTP_Services('SetResponseBody', Services, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseStatus', 500, '')
end
return
//----------------------------------------------------------------------------------------------------------------------
// Options
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
Options:
GoSub SetCommonOptionResponseHeaders
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SetGlobalResponseHeaders
//
// Since all authenticated API requests will start with the Entry Point, any authentication-dependent global response
// headers should be set here.
//----------------------------------------------------------------------------------------------------------------------
SetGlobalResponseHeaders:
return
//----------------------------------------------------------------------------------------------------------------------
// SetCommonOptionResponseHeaders
//
// Sets the response headers that will be common for all OPTIONS methods.
//----------------------------------------------------------------------------------------------------------------------
SetCommonOptionResponseHeaders:
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'x-authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Max-Age', 1728000)
GoSub SetAllowedMethods
return
//----------------------------------------------------------------------------------------------------------------------
// SetAllowedMethods
//
// Sets the Allow response header field as appropriate for the requested URL.
//----------------------------------------------------------------------------------------------------------------------
SetAllowedMethods:
If AllowedMethods NE '' then
For Each Method in AllowedMethods using ','
HTTP_Services('SetResponseHeaderField', 'Allow', Method, True$)
Next Method
end
return

View File

@ -0,0 +1,909 @@
Function HTTP_JSON_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_JSON_Services
Description : Handler program for all module related services.
Notes : The generic parameters should contain all the necessary information to process the services. Often
this will be information like the data Record and Key ID.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
02/06/15 dmb Original programmer. - [SRPFW-87]
04/17/15 dmb Added SetHALItem, SetHALCollection, and SetHALCollectionEmbedded services and removed
SetHALLinks, SetHALEmbedded, and GetHALRootObj services. These new services do a better
job of simplifying the creation of specific item and item collection HAL+JSON responses.
The GetHAL service remains but it has been modified to support the new services.
- [SRPFW-87]
04/17/15 dmb Converted /HTTPJSONServices/ labelled common into /HAL/ and /Schema/ labelled commons so
that the FreeCommon statement can be used. - [SRPFW-87]
04/19/15 dmb Update SetHALItem to support multivalue columns. - [SRPFW-87]
05/15/15 dmb Update SetHALCollectionEmbedded to allow responses with no embedded data. - [SRPFW-87]
06/09/15 dmb Restore SetHALLinks service as this does provide a valid response in some cases.
- [SRPFW-87]
06/09/15 dmb Add ItemArrayLabel argument to the GetHAL service so the calling service (usually
HTTP_Resources_Services) can specify the label text to use for the primary HAL array.
If not specified then "item" will be used as the default. - [SRPFW-87]
07/01/17 dmb Refactor using Enhanced BASIC+ syntax. - [SRPFW-184]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert SERVICE_SETUP
$insert HTTP_INSERTS
Declare function SRP_Sort_Array
Common /HAL/ HALType@, HALRootObj@, HALRootLinksObj@, HALEmbeddedObj@, HALItemArray@, HALLinksObj@
Common /Schema/ SchemaRootObj@, SchemaPropertiesObj@, SchemaRequiredArray@
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the HTTP Authentication services module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SetHALItem
//
// ItemURL - The URL to the item itself. - [Required]
// ColumnNames - An @FM delimited array of column names (i.e., dictionaries) that will label the column values.
// - [Required]
// ColumnValues - An @FM delimited array of column values (i.e., data) that represents the item resource. These are
// associated with the ColumnNames argument. - [Required]
// DataTypes - An @FM delimited array of JSON data types for each column value. If empty then SRP_JSON will decide
// using its default type matching rules. - [Optional]
// MVGroupNames - An @FM delimited array of MV group names. These are associated with the ColumnNames argument.
// - [Optional]
//
// Creates a HAL+JSON object for a specific item. Requires the GetHAL service to return the serialized object.
//----------------------------------------------------------------------------------------------------------------------
Service SetHALItem(ItemURL, ColumnNames, ColumnValues, DataTypes, MVGroupNames)
HALType@ = Service
If (ItemURL NE '') AND (ColumnNames NE '') AND (ColumnValues NE '') then
If MVGroupNames NE '' then
// MV group names have been passed in. Sort the arguments by the MV group names so these can be properly
// combined into the same JSON object.
Arguments = SRP_Sort_Array(ColumnNames : @RM : ColumnValues : @RM : DataTypes : @RM : MVGroupNames, 'AL4', False$, @RM, @FM)
ColumnNames = Arguments[1, @RM]
ColumnValues = Arguments[Col2() + 1, @RM]
DataTypes = Arguments[Col2() + 1, @RM]
MVGroupNames = Arguments[Col2() + 1, @RM]
end
PrevMVGroupName = ''
If HALRootObj@ NE '' else
// Create the root object.
If SRP_JSON(HALRootObj@, 'NEW', 'OBJECT') else
HTTP_Services('SetResponseError', '', '', 500)
Error_Services('Add', 'Error creating the HAL root object in the ' : Service : ' service.')
end
end
If Error_Services('NoError') then
// Create the "_links" object. It will be SET to the root object in the GetHAL service.
If SRP_JSON(HALRootLinksObj@, 'NEW', 'OBJECT') then
// Create the "self" object. It will be SET to the "_links" object when finished.
If SRP_JSON(hSelfObj, 'NEW', 'OBJECT') then
// Create the "href" name/value for the "self" object.
SRP_JSON(hSelfObj, 'SETVALUE', 'href', ItemURL)
// SET the "self" object to the "_links" object and name it.
If SRP_JSON(HALRootLinksObj@, 'SET', 'self', hSelfObj) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hSelfObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
// Create the "collection" object. It will be SET to the "_links" object when finished.
If SRP_JSON(hCollectionObj, 'NEW', 'OBJECT') then
// Create the "href" name/value for the "collection" object.
CollectionURL = ItemURL
ItemID = CollectionURL[-1, 'B/']
CollectionURL[-1, Neg(Len(ItemID) + 1)] = ''
SRP_JSON(hCollectionObj, 'SETVALUE', 'href', CollectionURL)
// SET the "collection" object to the "_links" object and name it.
If SRP_JSON(HALRootLinksObj@, 'SET', 'collection', hCollectionObj) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hCollectionObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
// Add the column name/value pairs. These are SETVALUEd to the root object.
ColumnNames = ColumnNames[1, @RM] ; // Make sure there are no "extra" items being added.
ColumnValues = ColumnValues[1, @RM] ; // Make sure there are no "extra" items being added.
DataTypes = DataTypes[1, @RM] ; // Make sure there are no "extra" items being added.
MVGroupNames = MVGroupNames[1, @RM] ; // Make sure there are no "extra" items being added.
NumColumns = DCount(ColumnNames, @FM)
For ColumnCnt = 1 to NumColumns
Name = ColumnNames<ColumnCnt>
Value = ColumnValues<ColumnCnt>
Type = DataTypes<ColumnCnt>
MVGroupName = MVGroupNames<ColumnCnt>
If Len(MVGroupName) then
// This column is a part of a MV group. Check to see if this is a new MV group or one that was
// already being used.
If MVGroupName NE PrevMVGroupName then
// A new MV group is being worked on.
If PrevMVGroupName NE '' then
// Create the JSON object for the new MV group.
If SRP_JSON(hMVArray, 'New', 'ARRAY') then
For MVValueCnt = 1 to MVTotalValues
If SRP_JSON(hMVObject, 'New', 'Object') then
For MVColumnCnt = 1 to MVTotalColumns
SRP_JSON(hMVObject, 'SetValue', MVLabels<MVColumnCnt>, MVArray<MVColumnCnt, MVValueCnt>)
Next MVColumnCnt
end
SRP_JSON(hMVArray, 'Add', hMVObject)
SRP_JSON(hMVObject, 'Release')
Next MVValueCnt
If SRP_JSON(HALRootObj@, 'Set', PrevMVGroupName, hMVArray) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hMVArray, 'Release')
end
end
MVLabels = ''
MVArray = ''
MVTotalColumns = 0
MVTotalValues = 0
end
MVLabels := Name : @FM
MVArray := Value : @FM
MVTotalColumns += 1
NumValues = DCount(Value, @VM)
If NumValues GT MVTotalValues then MVTotalValues = NumValues
* If SRP_JSON(hColumnArray, 'NEW', 'ARRAY') then
* NumValues = Count(Value, @VM) + (Value NE '')
* For ValueCnt = 1 to NumValues
* SRP_JSON(hColumnArray, 'ADDVALUE', Value<0, ValueCnt>)
* Next ValueCnt
* If SRP_JSON(hMVGroupObj@, 'SET', Name, hColumnArray) else HTTP_Services('SetResponseError', '', '', 500)
* SRP_JSON(hColumnArray, 'RELEASE')
* end
end else
If Index(Value, @VM, 1) then
If SRP_JSON(hColumnArray, 'NEW', 'ARRAY') then
NumValues = Count(Value, @VM) + (Value NE '')
For ValueCnt = 1 to NumValues
SRP_JSON(hColumnArray, 'ADDVALUE', Value<0, ValueCnt>)
Next ValueCnt
If SRP_JSON(HALRootObj@, 'SET', Name, hColumnArray) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hColumnArray, 'RELEASE')
end
end else
If SRP_JSON(HALRootObj@, 'SETVALUE', Name, Value, Type) else HTTP_Services('SetResponseError', '', '', 500)
end
end
Transfer MVGroupName to PrevMVGroupName
Next ColumnCnt
If PrevMVGroupName NE '' then
// Create the JSON object for the new MV group.
If SRP_JSON(hMVArray, 'New', 'ARRAY') then
For MVValueCnt = 1 to MVTotalValues
If SRP_JSON(hMVObject, 'New', 'Object') then
For MVColumnCnt = 1 to MVTotalColumns
SRP_JSON(hMVObject, 'SetValue', MVLabels<MVColumnCnt>, MVArray<MVColumnCnt, MVValueCnt>)
Next MVColumnCnt
end
SRP_JSON(hMVArray, 'Add', hMVObject)
SRP_JSON(hMVObject, 'Release')
Next MVValueCnt
If SRP_JSON(HALRootObj@, 'Set', PrevMVGroupName, hMVArray) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hMVArray, 'Release')
end
end
SRP_JSON(hMVGroupObj@, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end
end else
// At least one required argument is missing.
HTTP_Services('SetResponseError', '', '', 500)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetHALCollection
//
// CollectionURL - The URL to the collection. - [Required]
// ItemsURLs - An @FM delimited array of URLs to each item. - [Required]
// ItemsTitles - An @FM delimited array of item titles. These are associated with the ItemsURLs argument -
// [Required]
//
// Creates a HAL+JSON object for a collection. Requires the GetHAL service to return the serialized object.
//----------------------------------------------------------------------------------------------------------------------
Service SetHALCollection(CollectionURL, ItemsURLs, ItemsTitles)
HALType@ = Service
If (CollectionURL NE '') AND (ItemsURLs NE '') AND (ItemsTitles NE '') then
If HALRootObj@ NE '' else
// Create the root object.
If SRP_JSON(HALRootObj@, 'NEW', 'OBJECT') else
HTTP_Services('SetResponseError', '', '', 500)
Error_Services('Add', 'Error creating the HAL root object in the ' : Service : ' service.')
end
end
If Error_Services('NoError') then
If Len(HALRootLinksObj@) else
// Create the "_links" object. It will be SET to the root object in the GetHAL service.
If SRP_JSON(HALRootLinksObj@, 'NEW', 'OBJECT') then
// Create the "self" object. It will be SET to the "_links" object when finished.
If SRP_JSON(hSelfObj, 'NEW', 'OBJECT') then
// Create the "href" name/value for the "self" object.
SRP_JSON(hSelfObj, 'SETVALUE', 'href', CollectionURL)
// SET the "self" object to the "_links" object and name it.
If SRP_JSON(HALRootLinksObj@, 'SET', 'self', hSelfObj) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hSelfObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end
If Len(HALItemArray@) else
// Create the "item" array. This will hold the embedded items. It will be SET to the "_links" object
// in the GetHAL when service. It is left available now so multiple calls into the SetHALCollection
// service can be made in the event items needs to be added at different opportunities.
If SRP_JSON(HALItemArray@, 'NEW', 'ARRAY') else
HTTP_Services('SetResponseError', '', '', 500)
Error_Services('Add', 'Error creating the HAL item array in the ' : Service : ' service.')
end
end
If Error_Services('NoError') then
// ADD items to the "item" array.
NumItems = Count(ItemsURLs, @FM) + (ItemsURLs NE '')
For ItemCnt = 1 to NumItems
If SRP_JSON(hItemObj, 'NEW', 'OBJECT') then
ItemURL = Field(ItemsURLs, @FM, ItemCnt, 1)
ItemTitle = Field(ItemsTitles, @FM, ItemCnt, 1)
// Create the "href" name/value for the "item" object.
SRP_JSON(hItemObj, 'SETVALUE', 'href', ItemURL)
// Create the "title" name/value for the "item" object.
SRP_JSON(hItemObj, 'SETVALUE', 'title', ItemTitle)
// Add this item object to the "item" array.
SRP_JSON(HALItemArray@, 'ADD', hItemObj)
// Release the Item object handle.
SRP_JSON(hItemObj, 'RELEASE')
end
Next ItemCnt
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end
end else
// At least one required argument is missing.
HTTP_Services('SetResponseError', '', '', 500)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetHALCollectionEmbedded
//
// CollectionURL - The URL to the collection. - [Required]
// ItemsURLs - An @RM delimited array of URLs to each item. - [Required]
// ColumnNames - An @RM/@FM delimited array of column names (i.e., dictionaries) that will label the column values.
// These are associated with the ItemsURLs argument. - [Required]
// ColumnValues - An @RM/@FM delimited array of column values (i.e., data) that represents the item resource. These
// are associated with the ItemsURLs argument. - [Required]
// DataTypes - An @RM/@FM delimited array of JSON data types for each column value. If empty then SRP_JSON will
// decide using its default type matching rules. - [Optional]
// MVGroupNames - An @RM/@FM delimited array of MV group names. These are associated with the ItemsURLs argument.
// - [Optional]
//
// Creates a HAL+JSON object for a collection of embedded items. Requires the GetHAL service to return the serialized
// object.
//----------------------------------------------------------------------------------------------------------------------
Service SetHALCollectionEmbedded(CollectionURL, ItemsURLs, ColumnNames, ColumnValues, DataTypes, MVGroupNames)
HALType@ = Service
If CollectionURL NE '' then
If HALRootObj@ NE '' else
// Create the root object.
If SRP_JSON(HALRootObj@, 'NEW', 'OBJECT') else
HTTP_Services('SetResponseError', '', '', 500)
Error_Services('Add', 'Error creating the HAL root object in the ' : Service : ' service.')
end
end
If Error_Services('NoError') then
If HALRootLinksObj@ NE '' else
// Create the "_links" object. It will be SET to the root object in the GetHAL service.
If SRP_JSON(HALRootLinksObj@, 'NEW', 'OBJECT') then
// Create the "self" object. It will be SET to the "_links" object when finished.
If SRP_JSON(hSelfObj, 'NEW', 'OBJECT') then
// Create the "href" name/value for the "self" object.
SRP_JSON(hSelfObj, 'SETVALUE', 'href', CollectionURL)
// SET the "self" object to the "_links" object and name it.
If SRP_JSON(HALRootLinksObj@, 'SET', 'self', hSelfObj) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hSelfObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end
If HALEmbeddedObj@ NE '' else
// Create the "_embedded" object. This will contain the array of items. It will be SET to the root
// object in the GetHAL service. It is left available now so multiple calls into the
// SetHALCollectionEmbedded service can be made in the event items needs to be added at different
// opportunities.
If SRP_JSON(HALEmbeddedObj@, 'NEW', 'OBJECT') else
HTTP_Services('SetResponseError', '', '', 500)
Error_Services('Add', 'Error creating the HAL embedded object in the ' : Service : ' service.')
end
end
If HALItemArray@ NE '' else
// Create the "item" array. This will hold the embedded items. It will be SET to the "_embedded" object
// in the GetHAL when service. It is left available now so multiple calls into the
// SetHALCollectionEmbedded service can be made in the event items needs to be added at different
// opportunities.
If SRP_JSON(HALItemArray@, 'NEW', 'ARRAY') else
HTTP_Services('SetResponseError', '', '', 500)
Error_Services('Add', 'Error creating the HAL item array in the ' : Service : ' service.')
end
end
If Error_Services('NoError') then
// SET items to the "item" array.
NumItems = Count(ItemsURLs, @RM) + (ItemsURLs NE '')
For ItemCnt = 1 to NumItems
If SRP_JSON(hItemObj, 'NEW', 'OBJECT') then
ItemURL = Field(ItemsURLs, @RM, ItemCnt, 1)
ItemColumnNames = Field(ColumnNames, @RM, ItemCnt, 1)
ItemColumnValues = Field(ColumnValues, @RM, ItemCnt, 1)
ItemDataTypes = Field(DataTypes, @RM, ItemCnt, 1)
ItemMVGroupNames = Field(MVGroupNames, @RM, ItemCnt, 1)
If Len(ItemMVGroupNames) then
// MV group names have been passed in. Sort the arguments by the MV group names so these can be properly
// combined into the same JSON object.
Arguments = SRP_Sort_Array(ItemColumnNames : @RM : ItemColumnValues : @RM : ItemDataTypes : @RM : ItemMVGroupNames, 'AL4', False$, @RM, @FM)
ItemColumnNames = Arguments[1, @RM]
ItemColumnValues = Arguments[Col2() + 1, @RM]
ItemDataTypes = Arguments[Col2() + 1, @RM]
ItemMVGroupNames = Arguments[Col2() + 1, @RM]
end
PrevMVGroupName = ''
If SRP_JSON(hLinksObj, 'NEW', 'OBJECT') then
// Create the "self" object. It will be SET to the "_links" object when finished.
If SRP_JSON(hSelfObj, 'NEW', 'OBJECT') then
// Create the "href" name/value for the "self" object.
SRP_JSON(hSelfObj, 'SETVALUE', 'href', ItemURL)
// SET the "self" object to the "_links" object and name it.
If SRP_JSON(hLinksObj, 'SET', 'self', hSelfObj) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hSelfObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
// SET the "_links" object to the root object and name it.
If SRP_JSON(hItemObj, 'SET', '_links', hLinksObj) else HTTP_Services('SetResponseError', '', '', 500)
// Release the "links" object handle.
SRP_JSON(hLinksObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
NumColumns = Count(ItemColumnNames, @FM) + (ItemColumnNames NE '')
For ColumnCnt = 1 to NumColumns
Name = ItemColumnNames<ColumnCnt>
Value = ItemColumnValues<ColumnCnt>
Type = ItemDataTypes<ColumnCnt>
MVGroupName = ItemMVGroupNames<ColumnCnt>
If Len(MVGroupName) then
// This column is a part of a MV group. Check to see if this is a new MV group or one that was
// already being used.
If MVGroupName NE PrevMVGroupName then
// A new MV group is being worked on.
If Len(PrevMVGroupName) then
// There was a previous MV group started, then SET this to the MV group object.
If SRP_JSON(hItemObj, 'SET', PrevMVGroupName, hMVGroupObj@) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hMVGroupObj@, 'RELEASE')
end
// Create the JSON object for the new MV group.
If SRP_JSON(hMVGroupObj@, 'NEW', 'OBJECT') else HTTP_Services('SetResponseError', '', '', 500)
end
If SRP_JSON(hColumnArray, 'NEW', 'ARRAY') then
NumValues = Count(Value, @VM) + (Value NE '')
For ValueCnt = 1 to NumValues
SRP_JSON(hColumnArray, 'ADDVALUE', Value<0, ValueCnt>)
Next ValueCnt
If SRP_JSON(hMVGroupObj@, 'SET', Name, hColumnArray) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hColumnArray, 'RELEASE')
end
end else
If Index(Value, @VM, 1) then
If SRP_JSON(hColumnArray, 'NEW', 'ARRAY') then
NumValues = Count(Value, @VM) + (Value NE '')
For ValueCnt = 1 to NumValues
SRP_JSON(hColumnArray, 'ADDVALUE', Value<0, ValueCnt>)
Next ValueCnt
If SRP_JSON(hItemObj, 'SET', Name, hColumnArray) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hColumnArray, 'RELEASE')
end
end else
If SRP_JSON(hItemObj, 'SETVALUE', Name, Value, Type) else HTTP_Services('SetResponseError', '', '', 500)
end
end
Transfer MVGroupName to PrevMVGroupName
Next ColumnCnt
If Len(PrevMVGroupName) then
// There was a previous MV group started, then SET this to the MV group object.
If SRP_JSON(hItemObj, 'SET', PrevMVGroupName, hMVGroupObj@) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hMVGroupObj@, 'RELEASE')
end
// Add this item object to the "item" array.
SRP_JSON(HALItemArray@, 'ADD', hItemObj)
// Release the Item object handle.
SRP_JSON(hItemObj, 'RELEASE')
end
Next ItemCnt
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end else
// At least one required argument is missing.
HTTP_Services('SetResponseError', '', '', 500)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetHALLinks
//
// SelfURI - The URI to the self object. - [Required]
// HREFNames - An @FM delimited array of HREF names to add to the "links" object. - [Optional]
// HREFURIs - An @FM delimited array of HREF URIs to add to the "links" objects. These are associated with the
// HREFNames argument. - [Optional]
// ChildNames - An @FM delimited array of names for objects to add to the "links" object. - [Optional]
// hChildren - An @FM delimited array of objects handles to add to the "links" object. These are associated with
// the ChildNames argument.
// Names - An @FM delimited array of names to add to the "links" object. - [Optional]
// Values - An @FM delimited array of values to add to the "links" object. These are associated with the Names
// argument. -[Optional]
//
// Creates a HAL style "links" object.
//----------------------------------------------------------------------------------------------------------------------
Service SetHALLinks(SelfURI, HREFNames, HREFURIs, ChildNames, hChildren, Names, Values)
HALType@ = Service
If SelfURI NE '' then
If HALRootObj@ NE '' else
// Create the root object.
If SRP_JSON(HALRootObj@, 'NEW', 'OBJECT') else
HTTP_Services('SetResponseError', '', '', 500)
Error_Services('Add', 'Error creating the HAL root object in the ' : Service : ' service.')
end
end
If Error_Services('NoError') then
If HALRootLinksObj@ NE '' else
// Create the "_links" object. It will be SET to the root object in the GetHAL service.
If SRP_JSON(HALRootLinksObj@, 'NEW', 'OBJECT') then
// Create the "self" object. It will be SET to the "_links" object when finished.
If SRP_JSON(hSelfObj, 'NEW', 'OBJECT') then
// Create the "href" name/value for the "self" object.
SRP_JSON(hSelfObj, 'SETVALUE', 'href', SelfURI)
// SET the "self" object to the "_links" object and name it.
If SRP_JSON(HALRootLinksObj@, 'SET', 'self', hSelfObj) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hSelfObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end
// Create any "href" objects that are requested. These will be SET to the "_links" object when finished.
If HREFNames NE '' then
NumHREFs = Count(HREFNames, @FM) + (HREFNames NE '')
For HREFCnt = 1 to NumHREFs
HREFName = HREFNames<HREFCnt>
HREFURI = HREFURIs<HREFCnt>
// Create the "href" object. It will be SET to the "_links" object when finished.
If SRP_JSON(hHREFObj, 'NEW', 'OBJECT') then
// Create the "href" name/value for the "href" object.
SRP_JSON(hHREFObj, 'SETVALUE', 'href', HREFURI)
// SET the "href" object to the "_links" object and name it.
If SRP_JSON(HALRootLinksObj@, 'SET', HREFName, hHREFObj) then else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hHREFObj, 'RELEASE')
end else
HTTP_Services('SetResponseError', '', '', 500)
end
Next HREFCnt
end
// Add any chile name/object pairs that have been passed into this service. This are SET to the "links"
// object.
If ChildNames NE '' then
NumChildren = Count(ChildNames, @FM) + (ChildNames NE '')
For ChildCnt = 1 to NumChildren
ChildName = ChildNames<ChildCnt>
hChild = hChildren<ChildCnt>
If SRP_JSON(HALRootLinksObj@, 'SET', ChildName, hChild) else HTTP_Services('SetResponseError', '', '', 500)
While Error_Services('NoError')
Next ChildCnt
end
// Add any name/value pairs that have been passed into this service. These are SETVALUEd to the "links"
// object.
If Names NE '' then
NumNames = Count(Names, @FM) + (Names NE '')
For NameCnt = 1 to NumNames
Name = Names<NameCnt>
Value = Values<NameCnt>
If SRP_JSON(HALRootLinksObj@, 'SETVALUE', Name, Value) else HTTP_Services('SetResponseError', '', '', 500)
While Error_Services('NoError')
Next NameCnt
end
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetHALEmbedded
//
// Returns the handle to a root JSON object.
//----------------------------------------------------------------------------------------------------------------------
Service SetHALEmbedded()
end service
//----------------------------------------------------------------------------------------------------------------------
// GetHALRootObj
//
// Returns the handle to a root JSON object. If it does not already exist it will be created.
//----------------------------------------------------------------------------------------------------------------------
Service GetHALRootObj()
If HALRootObj@ NE '' else
// Create the root object.
If SRP_JSON(HALRootObj@, 'NEW', 'OBJECT') else HTTP_Services('SetResponseError', '', '', 500)
end
Response = HALRootObj@
end service
//----------------------------------------------------------------------------------------------------------------------
// GetHAL
//
// Returns the serialized JSON object for the current HAL response. If no HAL object has been defined then this will
// return an empty string and a 500 status code will be set. All HAL objects and arrays will be released in this
// service.
//----------------------------------------------------------------------------------------------------------------------
Service GetHAL(ItemArrayLabel)
HAL = ''
If (HALType@ NE '') AND (HALRootObj@ NE '') AND (HALRootLinksObj@ NE '') then
// Check the HAL Type (i.e., Collection or CollectionEmbedded) and perform any final association of
// objects and arrays. Release any objects and arrays.
Begin Case
Case HALType@ _EQC 'SetHALCollectionEmbedded'
If Len(HALEmbeddedObj@) AND Len(HALItemArray@) then
If Len(ItemArrayLabel) else ItemArrayLabel = 'item'
If SRP_JSON(HALEmbeddedObj@, 'SET', ItemArrayLabel, HALItemArray@) else HTTP_Services('SetResponseError', '', '', 500)
If SRP_JSON(HALRootObj@, 'SET', '_embedded', HALEmbeddedObj@) else HTTP_Services('SetResponseError', '', '', 500)
end
SRP_JSON(HALEmbeddedObj@, 'RELEASE')
SRP_JSON(HALItemArray@, 'RELEASE')
Case HALType@ _EQC 'SetHALCollection'
If Len(HALItemArray@) then
If Len(ItemArrayLabel) else ItemArrayLabel = 'item'
If SRP_JSON(HALRootLinksObj@, 'SET', ItemArrayLabel, HALItemArray@) else HTTP_Services('SetResponseError', '', '', 500)
end
SRP_JSON(HALItemArray@, 'RELEASE')
End Case
// Set the "_links" object to the root. This occurs for all HAL types.
If SRP_JSON(HALRootObj@, 'SET', '_links', HALRootLinksObj@) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(HALRootLinksObj@, 'RELEASE')
// Serialize the HAL object. Use STYLED for human readability or FAST for optimum performance and smaller payload.
* HAL = SRP_JSON(HALRootObj@, 'STRINGIFY', 'STYLED')
HAL = SRP_JSON(HALRootObj@, 'STRINGIFY', 'FAST')
SRP_JSON(HALRootObj@, 'RELEASE')
end
// Clear all HAL common variables.
FreeCommon 'HAL'
Response = HAL
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSchemaRootObj
//
// Returns the handle to a root Schema object. If it does not already exist it will be created with the standard
// "$schema" value already added.
//----------------------------------------------------------------------------------------------------------------------
Service GetSchemaRootObj()
If SchemaRootObj@ NE '' else
// Create the root object.
If SRP_JSON(SchemaRootObj@, 'NEW', 'OBJECT') then
If SRP_JSON(SchemaRootObj@, 'SETVALUE', '$schema', 'http://json-schema.org/draft-04/schema#') else HTTP_Services('SetResponseError', '', '', 500)
end else
HTTP_Services('SetResponseError', '', '', 500)
end
end
Response = SchemaRootObj@
end service
//----------------------------------------------------------------------------------------------------------------------
// SetSchemaMeta
//
// Title - The title for the schema. - [Optional]
// Description - A description for the schema. - [Optional]
// Type - The JSON type for the schema. The default value is "object". - [Optional]
//
// Sets the meta data associated to the schema object.
//----------------------------------------------------------------------------------------------------------------------
Service SetSchemaMeta(Title, Description, Type)
// Check for the root object. If none exists then create one and use it.
If Len(SchemaRootObj@) else SchemaRootObj@ = HTTP_JSON_Services('GetSchemaRootObj')
If Error_Services('NoError') then
If Type NE '' else Type = 'object'
If Title NE '' then
If SRP_JSON(SchemaRootObj@, 'SETVALUE', 'title', Title) else HTTP_Services('SetResponseError', '', '', 500)
end
If Description NE '' then
If SRP_JSON(SchemaRootObj@, 'SETVALUE', 'description', Description, 'STRING') else HTTP_Services('SetResponseError', '', '', 500)
end
If Type NE '' then
If SRP_JSON(SchemaRootObj@, 'SETVALUE', 'type', Type, 'STRING') else HTTP_Services('SetResponseError', '', '', 500)
end
end
end service
//----------------------------------------------------------------------------------------------------------------------
// SetSchemaProperty
//
// Name - The name of the member of this property. - [Required]
// Title - The title for this property. - [Optional]
// Type - The data type for this property. - [Optional]
// Format - The display format for this property. - [Optional]
// EnumList - A list of options that are to be used for this property. - [Optional]
// Required - Flag to indicate if this property is required. Default is false. - [Optional]
//
// Sets a property to the schema. There can be more than one property so this service will add another property to the
// list if it already exists.
//----------------------------------------------------------------------------------------------------------------------
Service SetSchemaProperty(Name, Title, Type, Format, EnumList, Required)
// Check for properties object handle. If none, create an object and use it.
If SchemaPropertiesObj@ NE '' else
SRP_JSON(SchemaPropertiesObj@, 'NEW', 'OBJECT')
end
If SchemaPropertiesObj@ NE '' then
If Name NE '' then
If SRP_JSON(hNameObj, 'NEW', 'OBJECT') then
// Add the Title member to the Name object.
If Title NE '' then
If SRP_JSON(hNameObj, 'SETVALUE', 'title', Title) else HTTP_Services('SetResponseError', '', '', 500)
end
// Add the Type member to the Name object.
If Type NE '' then
If SRP_JSON(hNameObj, 'SETVALUE', 'type', Type) else HTTP_Services('SetResponseError', '', '', 500)
end
// Add the Format member to the Name object.
If Format NE '' then
If SRP_JSON(hNameObj, 'SETVALUE', 'format', Format) else HTTP_Services('SetResponseError', '', '', 500)
end
// Add the EnumList array to the Name object.
If EnumList NE '' then
If SRP_JSON(hEnumAry, 'NEW', 'ARRAY') then
NumItems = Count(EnumList, @FM) + (EnumList NE '')
For ItemCnt = 1 to NumItems
If SRP_JSON(hEnumAry, 'ADDVALUE', EnumList<ItemCnt>) else HTTP_Services('SetResponseError', '', '', 500)
Next ItemCnt
If SRP_JSON(hNameObj, 'SET', 'enum', hEnumAry) else HTTP_Services('SetResponseError', '', '', 500)
SRP_JSON(hEnumAry, 'RELEASE')
end else
// Unable to create the Enum array.
HTTP_Services('SetResponseError', '', '', 500)
end
end
SRP_JSON(SchemaPropertiesObj@, 'SET', Name, hNameObj)
SRP_JSON(hNameObj, 'RELEASE')
If Required then
// Add members to the Required object.
If Len(SchemaRequiredArray@) else
SRP_JSON(SchemaRequiredArray@, 'NEW', 'ARRAY')
end
If Len(SchemaRequiredArray@) then
SRP_JSON(SchemaRequiredArray@, 'ADDVALUE', Name, 'STRING')
end
end
end else
// Unable to create the Name object.
HTTP_Services('SetResponseError', '', '', 500)
end
end else
// Name argument is missing.
HTTP_Services('SetResponseError', '', '', 500)
end
end else
// Unable to create the Schema Properties object.
HTTP_Services('SetResponseError', '', '', 500)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetSchema
//
// Returns the serialized JSON object for the current schema. If no schema object has been defined then this will return
// an empty string and a 500 status code will be set. All schema objects and arrays will be released in this service.
//----------------------------------------------------------------------------------------------------------------------
Service GetSchema()
Schema = ''
If SchemaRootObj@ NE '' then
SRP_JSON(SchemaRootObj@, 'SET', 'properties', SchemaPropertiesObj@)
SRP_JSON(SchemaRootObj@, 'SET', 'required', SchemaRequiredArray@)
Schema = SRP_JSON(SchemaRootObj@, 'STRINGIFY', 'FAST')
SRP_JSON(SchemaRequiredArray@, 'RELEASE') ; SchemaRequiredArray@ = ''
SRP_JSON(SchemaPropertiesObj@, 'RELEASE') ; SchemaPropertiesObj@ = ''
SRP_JSON(SchemaRootObj@, 'RELEASE') ; SchemaRootObj@ = ''
end else
HTTP_Services('SetResponseError', '', '', 500)
end
Response = Schema
end service
//----------------------------------------------------------------------------------------------------------------------
// GetURLFromID
//
// ID that needs to be converted to a URL format. - [Required]
//
// Returns a URL segment for the ID passed into the service. This creates a "slug" style URL so that it will be search
// friendly, human readable, and an RESTful.
//----------------------------------------------------------------------------------------------------------------------
Service GetURLFromID(ID)
URL = ID
// Convert all non-friendly URL characters into dashes.
Convert @Upper_Case to @Lower_Case in URL
Convert '!@#$%^&*()+=|<>?,./\"' : "'" to '' in URL
Convert '_' to '' in URL
URL = Trim(URL)
Convert ' ' to '-' in URL
Response = URL
end service
//----------------------------------------------------------------------------------------------------------------------
// GetIDFromURL
//
// URL that needs to be converted to an ID. Note, this is not a complete URL path. This should ordinarily be the end
// point of a URL. - [Required]
// A delimited array of IDs that can be used to validate the converted ID. Any MV delimiter can be used. If there is no
// match found then the ID will match the URL. - [Optional]
//
// Returns the ID based on the URL passed into the service. This service attempts to reverse engineer the URL.
//----------------------------------------------------------------------------------------------------------------------
Service GetIDFromURL(URL, Array, Table)
ID = URL
FoundID = False$
If Array NE '' then
Convert @STM to @FM in Array
Convert @TM to @FM in Array
Convert @SVM to @FM in Array
Convert @VM to @FM in Array
Convert @RM to @FM in Array
NumElements = Count(Array, @FM) + (Array NE '')
For ElementCnt = 1 to NumElements
MatchID = HTTP_JSON_Services('GetURLFromID', Array<ElementCnt>)
If ID _EQC MatchID then
ID = Array<ElementCnt>
FoundID = True$
end
Until FoundID
Next ElementCnt
end
If Not(FoundID) then Error_Services('Add', 'Unable to match the ID based on the provided URL')
Response = ID
end service

View File

@ -0,0 +1,195 @@
Function HTTP_MCP(Request, ProcErr)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_MCP (HTTP Master Controller Program)
Description : HTTP Controller program for the application.
Notes : In an MVC framework this is the 'Controller' routine that accepts HTTP requests nad routes them to
the core Master Controller Program (MCP). HTTP_MCP is written as a replacement to the
RUN_OECGI_REQUEST listner. It is intended to be a cleaner listener designed to allow REST style
API calls and better control over request and response handling. Since it is a listner, it should
be only modified when core functionality needs to be added or modified. Application specific
changes should be kept within one or more of the called services.
Parameters :
Request [in] -- The request array which includes the HTTP request and OECGI provided information.
ProcErr [in] -- Contains error messages in the event of a prior crash (such as a runtime error). The
specified listener is automatically called in these situations with the ProcErr argument
populated. Therefore, a check for data in this argument needs to occur immediately so that
the error can be properly managed and returned to the caller in a suitable format. For
RUN_OECGI_REQUEST applications, INET_ABORTED would normally be called to handle this.
Response [out] -- HTTP response to send back to the OECGI.
History : (Date, Initials, Notes)
02/06/15 dmb [SRPFW-90] Original programmer. Copied from INET_MCP but refactored for REST API requests.
04/14/15 dmb [SRPFW-90] Add missing '\' in the path for debug files to be written to.
02/23/16 dmb [SRPFW-103] Move the request/response capture path defintion into the
SYSENV\SRP_HTTP_FRAMEWORK_SETUP record.
02/25/16 dmb [SRPFW-108] Replace Xlate with GetCapturePath service.
03/09/16 dmb [SRPFW-111] Call GetEntryPointService before calling RunHTTPService.
03/09/16 dmb [SRPFW-112] Remove HTTP_SERVICE_SETUP insert.
03/09/16 dmb [SRPFW-112] Call GetHTTPPathInfo before calling RunHTTPService.
05/17/16 dmb [SRPFW-125] Add support for ProcErr. Create a generic error response.
10/01/16 dmb [SRPFW-128] Add code to track API execution time using SRP_Stopwatch. Display the time in
the Response log that is written into the debug folder.
02/18/17 dmb [SRPFW-151] Report the decoded Authorization data in the Response log.
02/27/17 dmb [SRPFW-125] Add support for the GetProcErrService service. If missing, the default ProcErr
process logic will continue to work.
03/03/17 dmb [SRPFW-154] Replace direct logging with the CreateLogFile service.
03/08/17 dmb [SRPFW-155] Add support for setting the debugger mode and intercept.
07/01/17 dmb [SRPFW-184] Refactor using Enhanced BASIC+ syntax.
11/01/18 dmb [SRPFW-256] Add support for the GetServerEnabled service. Set status to 503 is server is not
enabled.
11/18/18 dmb [SRPFW-257] Add support for the GetAPICallProcedure service. Use the RunWebAPI or
RunHTTPService service as appropriate.
12/12/18 dmb [SRPFW-257] If Get_Status returns an error, produce a GetStatus log and then use the
SetResponseError service so the client gets a detailed response.
12/16/19 dmb [SRPFW-296] Update code that calls the CreateLogFile service for Get_Status conditions so
that the status detail is better formatted. Also, clear the error condition to prevent
the OECGI from making a ProcErr call.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert HTTP_INSERTS
$insert INET_EQUATES
$insert INET_HEADERS
$insert Msg_Equates
Equ CRLF$ to \0D0A\
Declare subroutine SRP_Stopwatch, Set_Status, RTI_Set_Debugger
Declare function SRP_Stopwatch, RTI_OS_Directory
If Assigned(Request) else Request = ''
If Assigned(ProcErr) else ProcErr = ''
If ProcErr NE '' then
// Runtime errors produce two copies of the error description in the ProcErr argument. Just divide in half to get
// one copy.
If ProcErr[1, Len(ProcErr) / 2] EQ ProcErr[Len(ProcErr) / 2 + 1, Len(ProcErr) / 2] then
ProcErr = ProcErr[1, Len(ProcErr) / 2]
end
end
// Start timing the overall API.
SRP_Stopwatch('Reset')
SRP_Stopwatch('Start', 'WebAPI')
// Set the mode for the debugger and identify the debugger intercept service if applicable.
DebuggerSetting = HTTP_Services('GetDebuggerSetting')
If DebuggerSetting EQ 2 then
DebuggerService = HTTP_Services('GetDebuggerService')
end else
DebuggerService = ''
end
RTI_Set_Debugger(DebuggerSetting, DebuggerService)
// Use HTTP_Services to store the HTTP request as provided by the OECGI and also to retreive the relevant request
// information that will be used below.
HTTP_Services('SetSessionID')
HTTP_Services('SetOECGIRequest', Request)
HTTP_Services('SetOECGIProcErr', ProcErr)
HTTP_Services('SetRequestHeaderFields')
HTTP_Services('SetQueryFields')
// Create the HTTP Request log file.
HTTP_Services('CreateLogFile', 'Request')
If ProcErr NE '' then
// An unexpected error occurred with the most recent request. The nature of the error (usually a runtime error) will
// be contained in the ProcErr argument. Generate a response so the caller will receive a well formatted reply.
AbortedService = HTTP_Services('GetAbortedService')
If AbortedService NE '' then
// There is a procedural error service designated to handle this condition. Allow it to process the error and
// generate the response.
Call @AbortedService(ProcErr)
end else
// There is no procedural error service so process this using default logic.
Swap \00\ with \0D0A\ in ProcErr
Swap @FM with \0D0A\ in ProcErr
Swap @VM with \0D0A\ in ProcErr
Swap @SVM with \0D0A\ in ProcErr
// The ProcErr always contains two copies of the error description so just divide in half to get one copy.
If ProcErr[1, Len(ProcErr) / 2] EQ ProcErr[Len(ProcErr) / 2 + 1, Len(ProcErr) / 2] then
ProcErr = ProcErr[1, Len(ProcErr) / 2]
end
HTTP_Services('SetResponseError', '', '', 500, ProcErr, FullEndpointURL)
end
end else
ServerEnabled = HTTP_Services('GetServerEnabled')
// Check to see if the server is still enabled.
If ServerEnabled then
// Authenticate the request using HTTP Authentication Services. If the user is not validated then the appropriate
// response status and headers will be set. If no authentication is required then the AuthenticateRequest service
// should set the UserAuthenticated response to True as a default.
//
// This service is also where global response headers are set, regardless of whether the user is authenticated.
//
// Note: Even if authentication is disabled via the SRP_HTTP_FRAMEWORK_SETUP configuration record, the
// AuthenticateRequest should still be called. It will inspect the flag and set the response accordingly.
UserAuthenticated = HTTP_Authentication_Services('AuthenticateRequest')
If UserAuthenticated then
// Call the API based on the type of calling procedure specified in the setup.
APICallProcedure = HTTP_Services('GetAPICallProcedure')
If APICallProcedure EQ 'Web API' then
HTTP_Services('RunWebAPI')
end else
EntryPointService = HTTP_Services('GetEntryPointService')
RemainingURL = HTTP_Services('GetHTTPPathInfo')
HTTP_Services('RunHTTPService', EntryPointService, RemainingURL)
end
end
end else
HTTP_Services('SetResponseError', '', '', 503, 'Server is temporarily disabled.')
end
end
// Get the full response to send back to the requesting client.
Response = HTTP_Services('GetResponse')
// Stop timing the overall API.
SRP_Stopwatch('Stop', 'WebAPI')
TimeToExecute = SRP_Stopwatch('GetBenchmark', 'WebAPI')
// Check the status before logging and returning the HTTP Response. If there is a status error then the Response
// variable should be cleared and no log generated. The OEngineServer will resubmit a request with the error detail
// the the ProcErr service will handle and log this.
If Get_Status() EQ 0 then
HTTP_Services('CreateLogFile', 'Response', Response)
end else
StatusCode = ''
Status = Get_Status(StatusCode)
HTTP_Services('SetResponseError', '', '', 500, 'Get_Status Error', FullEndpointURL, 'Status' : @FM : 'StatusCode', Status : @FM : StatusCode<1, 1> : ' - ' : StatusCode<1, 2>)
Response = HTTP_Services('GetResponse')
HTTP_Services('CreateLogFile', 'GetStatus', Response)
Set_Status(0)
end
// Engage the debugger if requested.
If HTTP_Services('GetRequestHeaderField', 'Debug') then Debug
// Clear all saved values that were set in this session to avoid subsequent requests to a running engine from getting
// invalid data.
HTTP_Services('ClearSettings')
// Clean up processes, as needed, that were set in this session to avoid subsequent requests to a running engine from
// getting invalid data.
HTTP_Authentication_Services('CleanUp')
// Clear any possible internal OpenInsight errors so everything will process normally. Note, traditional INET does not
// clear this flag automatically. This is how INET_ABORTED gets called if there is an SSP error. The SRP HTTP Framework
// clears this flag by default because the developer can still trap Get_Status() in the relevant web service code and
// create a custom HTTP response. Thus, the ProcErr service will only be called if there is a runtime error condition.
* Set_Status(0)
Return Response

View File

@ -0,0 +1,252 @@
Function HTTP_Picture_Services(RemainingURL)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Picture_Services
Description : Handler program for the HTTP Picture service module.
Notes : All HTTP web services should include the HTTP_SERVICE_SETUP insert. This will provide several useful
variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
SelfURL - The URL path representing the current service.
FullEndPointURL - The URL submitted by the client. This can be the same or longer than
the SelfURL.
NextSegment - The URL segment immediately following the SelfURL (if any). This
could contain the name of the next service or it could contain the
Item ID for the current service (aka resource).
CurrentServiceHandler - The name of this stored procedure.
Parameters :
RemainingURL [in] -- The remaining portion of the URL that follows the URL that launched this current
service. This information is used in the HTTP_SERVICE_SETUP insert to populate other
useful variables (see Notes above).
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
03/27/16 dmb Original programmer. - [SRPFW-96]
07/06/17 dmb Refactor using Enhanced BASIC+ syntax. - [SRPFW-184]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_SERVICE_SETUP
$insert HTTP_INSERTS
$insert CONTACTS_EQUATES
// Assume the current HTTP method is valid until proven otherwise.
ValidMethod = True$
// Assume the current web service is valid until provent otherwise.
ValidService = True$
// Assume no HTTP methods are valid until proven otherwise.
AllowedMethods = ''
// A list of all services able to be called from this URL.
AllowedServices = ''
PictureFolder = '\WebAppData\ContactPictures\'
// Handle the HTTP request as needed.
Begin Case
Case RemainingURL _EQC ''
// This means the URL ends with /contacts/{KeyID}/picture, which means this is the end point.
AllowedMethods = 'PUT,GET,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub Put, Get, Options
end else
ValidMethod = False$
end
Case Otherwise$
ValidService = False$
End Case
// Resolve any invalid conditions with the HTTP request.
Begin Case
Case Not(ValidService)
HTTP_Services('SetResponseStatus', 404, NextSegment : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
Case Not(ValidMethod)
HTTP_Services('SetResponseStatus', 405, HTTPMethod : ' is not valid for this service.')
GoSub SetAllowedMethods
End Case
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Web Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// Put
//
// Attempts to update the picture resource at this URL end point.
//----------------------------------------------------------------------------------------------------------------------
Put:
NumSegments = DCount(SelfURL, '/')
KeyID = Field(SelfURL, '/', NumSegments - 1, 1)
TableName = 'CONTACTS'
Open TableName to hTable then
Lock hTable, KeyID then
ResponseStatus = 200 ; // Updating an existing resource.
Read DataRow from hTable, KeyID else
DataRow = ''
ResponseStatus = 201 ; // Creating a new resource.
end
// A URI scheme of the Base64 encoded image will be in the Data variable.
HTTPPostString = HTTP_Services('GetHTTPPostString')
HTTPPostString = HTTP_Services('DecodePercentString', HTTPPostString)
Scheme = HTTPPostString[1, 'F:']
If Scheme _EQC 'data' then
MediaType = HTTPPostString[Col2() + 1, 'F;'] ; // Should be "image/png" or "image/jpg"
Encoding = HTTPPostString[Col2() + 1, 'F,'] ; // Should be "base64"
EncodedData = HTTPPostString[Col2() + 1, Len(HTTPPostString)] ; // Should be the actual Base64 encoded content.
DecodedData = SRP_Decode(EncodedData, 'BASE64')
FileType = MediaType[-1, 'B/']
FileName = KeyID : '.' : FileType
FilePath = Drive() : PictureFolder : FileName
Status() = 0
OSWrite DecodedData to FilePath
StatusCode = Status()
If StatusCode then
Begin Case
Case StatusCode EQ 1 ; Error = 'Bad OS filename. Code: ' : StatusCode
Case StatusCode EQ 2 ; Error = 'Access denied by operating system. Code: ' : StatusCode
Case StatusCode EQ 3 ; Error = 'Disk or directory full. Code: ' : StatusCode
Case StatusCode EQ 4 ; Error = 'File does not exist. Code: ' : StatusCode
Case StatusCode EQ 5 ; Error = 'Unknown error. Code: ' : StatusCode
Case StatusCode EQ 6 ; Error = 'Attempt to write to read-only file. Code: ' : StatusCode
Case Otherwise$ ; Error = 'Unknown error. Code: ' : StatusCode
End Case
HTTP_Services('SetResponseStatus', '501', Error)
end else
DataRow<CONTACTS_PICTURE$> = PictureFolder : FileName
Write DataRow to hTable, KeyID then
HTTP_Services('SetResponseStatus', ResponseStatus)
HTTP_Services('SetResponseHeaderField', 'Content-Location', SelfURL)
end else
HTTP_Services('SetResponseStatus', 500, 'Error writing ' : KeyID : ' to the ' : TableName : ' table.')
end
end
end else
HTTP_Services('SetResponseStatus', '415')
end
Unlock hTable, KeyID else Null
end else
HTTP_Services('SetResponseStatus', 423, KeyID : ' is currently locked.')
end
end else
HTTP_Services('SetResponseStatus', 500, 'Error opening the ' : TableName : ' table.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// Get
//
// Attempts to return the picture resource from this URL end point.
//----------------------------------------------------------------------------------------------------------------------
Get:
// Get the picture's physical file path from the CONTACT database row.
NumSegments = DCount(SelfURL, '/')
KeyID = Field(SelfURL, '/', NumSegments - 1, 1)
PicturePath = Drive() : HTTP_Resource_Services('GetColumnValues', 'CONTACTS', 'picture', KeyID)
If PicturePath NE '' then
// Verify the picture actually exists.
If Dir(PicturePath) NE '' then
// Get the image extension.
ImageExt = PicturePath[-1, 'B.']
If ImageExt _EQC 'jpg' then ImageExt = 'jpeg'
// Get the best content type that matches the client's and server's ability.
ContentType = HTTP_Services('GetBestContentNegotiation', 'Accept', 'text/plain' : @FM : 'image/' : ImageExt)
If ContentType NE '' then
OSRead PictureBinary from PicturePath then
Begin Case
Case ContentType _EQC 'text/plain'
PictureBody = SRP_Encode(PictureBinary, 'BASE64')
PictureBody = 'data:' : 'image/' : ImageExt : ';base64,' : PictureBody
HTTP_Services('SetResponseHeaderField', 'Content-Encoding', 'base64')
HTTP_Services('SetResponseBody', PictureBody, False$, 'text/plain')
Case ContentType[1, 6] _EQC 'image/'
HTTP_Services('SetResponseBody', PictureBinary, True$, ContentType)
End Case
end
end
end else
HTTP_Services('SetResponseStatus', '404', 'Picture for contact ' : KeyID : ' does not exist.')
end
end else
HTTP_Services('SetResponseStatus', '404', 'Picture for contact ' : KeyID : ' does not exist.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// Options
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
Options:
GoSub SetCommonOptionResponseHeaders
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SetCommonOptionResponseHeaders
//
// Sets the response headers that will be common for all OPTIONS methods.
//----------------------------------------------------------------------------------------------------------------------
SetCommonOptionResponseHeaders:
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'x-authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Max-Age', 1728000)
GoSub SetAllowedMethods
return
//----------------------------------------------------------------------------------------------------------------------
// SetAllowedMethods
//
// Sets the Allow response header field as appropriate for the requested URL.
//----------------------------------------------------------------------------------------------------------------------
SetAllowedMethods:
If AllowedMethods NE '' then
For Each Method in AllowedMethods using ','
HTTP_Services('SetResponseHeaderField', 'Allow', Method, True$)
Next Method
end
return

View File

@ -0,0 +1,582 @@
Function HTTP_Resource_Manager_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Resource_Manager_Services
Description : Handler program for all module related services.
Notes : The generic parameters should contain all the necessary information to process the services. Often
this will be information like the data Record and Key ID.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
07/12/19 dmb [SRPFW-277] Original programmer.
07/13/19 dmb [SRPFW-277] Added various services so that the NDW_HTTP_FRAMEWORKS_SERVICES commuter as well
as additional tools can get or set various resource meta data.
07/15/19 dmb [SRPFW-277] Added the GetEndpointResourceKeyID service.
07/16/19 dmb [SRPFW-277] Added the GetResourceSignature service.
07/16/19 dmb [SRPFW-277] Update GetResourceProperty service to support the RESOURCE property.
07/16/19 dmb [SRPFW-277] Replaced harcoded cache duration with the CacheTTL$ equate.
07/16/19 dmb [SRPFW-277] Rename the IsResource service to IsValidEndpoint.
07/17/19 dmb [SRPFW-277] Update the SetResource service to refresh the GetResource cache better.
07/24/19 dmb [SRPFW-278] Fix bug in the GetEndpointResourceKeyID service so that matching the URLEndpoint
works better.
09/25/19 dmb [SRPFW-278] Fix bug in the GetResource service that prevented endpoints with a resource ID
from being matched correctly to the currently stored resources endpoints.
12/09/19 dmb [SRPFW-296] Update all calls to Memory_Services to use a specific cache name.
01/23/20 dmb [SRPFW-296] Update the SetResourceProperty and GetResourceSignature services to support the
HEAD method.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert HTTP_INSERTS
$insert SERVICE_SETUP
$insert INET_EQUATES
$insert INET_HEADERS
$insert HTTP_FRAMEWORK_SETUP_EQUATES
Equ CRLF$ to \0D0A\
Equ CacheTTL$ to 300 ; // Allow cached data to only be fresh for 5 seconds.
Equ CacheName$ to 'SRPHTTPFramework'
Equ ValidMethods$ to 'GET,POST,PUT,PATCH,DELETE,HEAD'
Declare function HTTP_Resource_Manager_Services, HTTP_Resource_Services, Database_Services, Memory_Services, SRP_Array
Declare subroutine HTTP_Resource_Manager_Services, HTTP_Resource_Services, Database_Services, Memory_Services
GoToService else
HTTP_Services('SetResponseError', '', '', 404, Service : ' is not a valid service request within the HTTP Resource Manager services module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
Options CLASSES = 'APIROOT', 'RESOURCE', 'RESOURCE_ID', 'PROPERTY'
Options PROPERTIES = 'CLASS', 'DESCRIPTION', 'EXCLUDE_LOGGING', 'METHODS', 'NAME', 'RESOURCE', 'TITLE', 'QUERY_PARAMS'
Options CHILDREN = 'ALL', 'RESOURCE', 'RESOURCE_ID', 'PROPERTY'
Options METHODS = 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// GetResourceProperty
//
// URLEndpoint - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// PropertyName - Name of the property whose value is being queried. - [Required]
//
// Returns the value of the indicated resource property for the indicated URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceProperty(URLEndpoint, PropertyName=PROPERTIES)
PropertyValue = ''
If PropertyName NE '' then
Resource = HTTP_Resource_Manager_Services('GetResource', URLEndpoint)
If Error_Services('NoError') then
PropertyNames = Resource<1>
Locate PropertyName in PropertyNames using @VM setting PropertyPos then
PropertyValue = Resource<2, PropertyPos>
end
Begin Case
Case PropertyName EQ 'EXCLUDE_LOGGING'
// This property defaults to false unless true.
If PropertyValue NE True$ then PropertyValue = False$
Case PropertyName EQ 'RESOURCE' AND PropertyValue = ''
// Unless the system has forced this property to store a value, it should be derived from the
// resource signature.
Signature = HTTP_Resource_Manager_Services('GetResourceSignature', URLEndpoint)
PropertyValue = Signature[1, '.']
End Case
end
end else
Error_Services('Add', 'PropertyName argument was missing in the ' : Service : ' service.')
end
Response = PropertyValue
end service
//----------------------------------------------------------------------------------------------------------------------
// SetResourceProperty
//
// URLEndpoint - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// PropertyName - Name of the property whose value is being set. - [Required]
// PropertyValue - Value of the property being updated. Depending upon the property, this might clear the value or
// set a default value. - [Optional]
//
// Sets (or updates) the value of the indicated resource property for the indicated URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service SetResourceProperty(URLEndpoint, PropertyName=PROPERTIES, PropertyValue)
If PropertyName NE '' then
Resource = HTTP_Resource_Manager_Services('GetResource', URLEndpoint)
If Error_Services('NoError') then
PropertyNames = Resource<1>
Begin Case
Case PropertyName EQ 'METHODS'
// Make sure only valid HTTP methods are set.
Transfer PropertyValue to Methods
For Each Method in Methods using ',' setting cPos
Locate Method in ValidMethods$ using ',' setting MethodPos then
PropertyValue := Method : ','
end
Next Method
PropertyValue[-1, 1] = ''
Case PropertyName EQ 'EXCLUDE_LOGGING'
// This property defaults to false unless true.
If PropertyValue NE True$ then PropertyValue = False$
Case PropertyName EQ 'CLASS'
// Make sure only a valid resource class is set.
Locate PropertyValue in 'RESOURCE,RESOURCE_ID,PROPERTY' using ',' setting ClassPos else
PropertyValue = 'RESOURCE'
end
End Case
Locate PropertyName in PropertyNames using @VM setting PropertyPos else
Resource<1, PropertyPos> = PropertyName
end
Resource<2, PropertyPos> = PropertyValue
HTTP_Resource_Manager_Services('SetResource', URLEndpoint, Resource)
end
end else
Error_Services('Add', 'PropertyName argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResourceChildren
//
// URLEndpoint - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// ChildType - Type of child resource being queried. If empty or ALL then all children are returned. - [Optional]
//
// Returns an @FM delimited list of URL endpoints matching the indicated child type that are children to the indicated
// URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceChildren(URLEndpoint, ChildType=CHILDREN)
Children = ''
ResourceList = HTTP_Resource_Manager_Services('GetResourceList')
If Error_Services('NoError') then
// Loop through the resource list to find resource children.
If ResourceList NE '' then
Locate ChildType in 'ALL,RESOURCE,RESOURCE_ID,PROPERTY' using ',' setting ChildPos else
ChildType = 'ALL'
end
ThisEndpointKeyID = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)
ThisLevel = DCount(ThisEndpoint, '/')
For Each ResourceItem in ResourceList using @FM
Endpoint = ResourceItem<0, 2>
EndpointLevel = DCount(Endpoint, '/')
If EndpointLevel EQ 2 then
EndpointParent = 'APIROOT'
end else
EndpointParent = Field(Endpoint, '/', 1, EndpointLevel - 1)
end
If EndpointParent _EQC ThisEndpointKeyID then
EndpointType = ResourceItem<0, 5>
If (EndpointType EQ ChildType) OR (ChildType EQ 'ALL') then
Children := Endpoint : @FM
end
end
Next ResourceItem
end
end
Children[-1, 1] = ''
Response = Children
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResourceSignature
//
// URLEndpoint - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// Method - HTTP method for the signature. This must be a valid method but it can also be empty. If empty,
// the signature returned will simply omit the method. - [Optional]
//
// Returns the API calling signature for the indicated URL endpoint. This is used by the RunWebAPI service (a member of
// HTTP_Services) when calling the Web API module.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceSignature(URLEndpoint, Method=METHODS)
Signature = ''
URLEndpointKeyID = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)
// Validate the HTTP method.
Locate Method in ValidMethods$ using ',' setting MethodPos else
Method = ''
end
If URLEndpointKeyID EQ 'APIROOT' then
Signature = 'APIROOT.'
end else
ThisLevel = DCount(URLEndpointKeyID, '/')
For LevelCnt = 2 to ThisLevel
Class = HTTP_Resource_Manager_Services('GetResourceProperty', Field(URLEndpointKeyID, '/', 1, LevelCnt), 'CLASS')
Begin Case
Case Class EQ 'RESOURCE'
// A resource starts a new signature.
Signature = Field(URLEndpointKeyID, '/', LevelCnt, 1) : '.'
Case Class EQ 'RESOURCE_ID'
Signature := 'ID.'
Case Otherwise$
Signature := Field(URLEndpointKeyID, '/', LevelCnt, 1) : '.'
End Case
Next LevelCnt
end
If Method NE '' then
Signature := Method
end else
Signature[-1, 1] = ''
end
Response = Signature
end service
//----------------------------------------------------------------------------------------------------------------------
// GetEndpointResourceKeyID
//
// URLEndpoint - URL endpoint to be validated. If empty, the APIROOT resource will be returned. - [Optional]
// AllowNew - Boolean flag indicating if a URL endpoint can be returned if new. Default is false. - [Optional]
//
// Returns the resource Key ID for the indicated URL endpoint. If AllowNew is true, a URL endpoint will be returned that
// best matches the available endpoints but it will not be cached.
//----------------------------------------------------------------------------------------------------------------------
Service GetEndpointResourceKeyID(URLEndpoint, AllowNew)
ServiceKeyID := '*' : URLEndpoint
ResourceKeyID = Memory_Services('GetValue', ServiceKeyID, True$, CacheTTL$, CacheName$)
ResourceKeyIDFound = True$ ; // Assume true for now.
If AllowNew NE True$ then AllowNew = False$
IsNew = False$ ; // Assume false for now.
If ResourceKeyID EQ '' then
If (URLEndpoint EQ '') OR (URLEndpoint _EQC 'APIROOT') then
ResourceKeyID = 'APIROOT'
end else
// Make sure the URL endpoint is well formed. The intent is for the incoming URL endpoint to be forgiving but
// internally it needs to match with the exact format of the endpoints used to uniquely identify each resource.
Swap 'https' with '' in URLEndpoint
Swap 'http' with '' in URLEndpoint
HomeURL = HTTP_Services('GetHomeURL')
Swap 'https' with '' in HomeURL
Swap 'http' with '' in HomeURL
APIURL = HTTP_Services('GetAPIRootURL', False$)
If URLEndpoint[-1, 1] EQ '/' then URLEndpoint[-1, 1] = ''
// Remove references to the Home or API URLs since these are not used when creating the resource endpoint
// identifiers.
Swap HomeURL with '' in URLEndpoint
Swap APIURL with '' in URLEndpoint
If URLEndpoint EQ '' then
// An empty URL endpoint implies APIROOT.
ResourceKeyID = 'APIROOT'
end else
// The URL endpoint needs to be walked one segment at a time to confirm that it matches the pattern of
// an existing resource endpoint. Since the true URL endpoint might contains a resource ID, there needs
// to be a check to see if the value of a given segment matches a defined resource or resource property
// first. If not, then confirm there is a resource ID defined for this segment.
ResourceList = HTTP_Resource_Manager_Services('GetResourceList')
ResourceArray = SRP_Array('Rotate', ResourceList, @FM , @VM)
ResourceEndpoints = ResourceArray<2>
ResourceNames = ResourceArray<3>
ResourceClasses = ResourceArray<5>
// Since the stored resource endpoints contain user defined resource IDs, each of these need to be
// converted to a generic '{ResourceID}' so simple comparison logic can work.
For Each Class in ResourceClasses using @VM setting ClassPos
If Class EQ 'RESOURCE_ID' then
OrigResourceEndpoint = ResourceEndpoints<0, ClassPos>
ResourceEndpoint = OrigResourceEndpoint
ResourceName = ResourceNames<0, ClassPos>
Swap ResourceName with '{ResourceID}' in ResourceEndpoint
Swap OrigResourceEndpoint with ResourceEndpoint in ResourceEndpoints
end
Next Class
Convert @Upper_Case to @Lower_Case in ResourceEndpoints
Convert @Upper_Case to @Lower_Case in URLEndpoint
// Remove any preceding "/" characters so the For Each will work
// better.
If URLEndpoint[1, 1] EQ '/' then URLEndpoint = URLEndpoint[2, 9999]
MatchResourceKeyID = ''
// Walk the URL endpoint provided and check for matches. Build the resource Key ID along the way. If a
// given segment is unable to be matched to a defined resource endpoint, end the loop and clear the
// resource Key ID.
FinalSegment = False$
For Each Segment in URLEndpoint using '/' setting SegmentPos
MatchResourceKeyID := '/' : Segment
Locate MatchResourceKeyID in ResourceEndpoints using @VM setting URLPos then
If Segment[1, 1] EQ '{' then
ResourceKeyID := '/{resourceid}'
end else
ResourceKeyID := '/' : Segment
end
end else
MatchResourceKeyID = Field(MatchResourceKeyID, '/', 1, SegmentPos) : '/{resourceid}'
Locate MatchResourceKeyID in ResourceEndpoints using @VM setting URLPos then
ResourceKeyID := '/{resourceid}'
end else
If AllowNew EQ True$ then
ResourceKeyID := '/' : Segment
IsNew = True$
end else
FinalSegment = True$
end
end
end
While (ResourceKeyIDFound EQ True$) AND (FinalSegment EQ False$)
Next Segment
end
end
If ResourceKeyIDFound EQ True$ then
If IsNew NE True$ then
Memory_Services('SetValue', ServiceKeyID, ResourceKeyID, CacheName$)
end
end else
ResourceKeyID = ''
end
end
Response = ResourceKeyID
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResource
//
// URLEndpoint - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
//
// Returns an array of resource property names and values for the indicated URL endpoint.
//----------------------------------------------------------------------------------------------------------------------
Service GetResource(URLEndpoint)
URLEndpointKeyID = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)
ServiceKeyID := '*' : URLEndpointKeyID
Resource = Memory_Services('GetValue', ServiceKeyID, True$, CacheTTL$, CacheName$)
If Resource EQ '' then
ResourceList = HTTP_Resource_Manager_Services('GetResourceList')
If Error_Services('NoError') then
// The URL endpoint needs to be walked one segment at a time to confirm that it matches the pattern of
// an existing resource endpoint. Since the true URL endpoint might contains a resource ID, there needs
// to be a check to see if the value of a given segment matches a defined resource or resource property
// first. If not, then confirm there is a resource ID defined for this segment.
ResourceArray = SRP_Array('Rotate', ResourceList, @FM , @VM)
ResourceEndpoints = ResourceArray<2>
ResourceNames = ResourceArray<3>
ResourceClasses = ResourceArray<5>
// Since the stored resource endpoints contain user defined resource IDs, each of these need to be
// converted to a generic '{ResourceID}' so simple comparison logic can work.
For Each Class in ResourceClasses using @VM setting ClassPos
If Class EQ 'RESOURCE_ID' then
OrigResourceEndpoint = ResourceEndpoints<0, ClassPos>
ResourceEndpoint = OrigResourceEndpoint
ResourceName = ResourceNames<0, ClassPos>
Swap ResourceName with '{ResourceID}' in ResourceEndpoint
Swap OrigResourceEndpoint with ResourceEndpoint in ResourceEndpoints
end
Next Class
Convert @Upper_Case to @Lower_Case in ResourceEndpoints
MatchURLEndpointKeyID = URLEndpointKeyID
Convert @Upper_Case to @Lower_Case in MatchURLEndpointKeyID
Locate MatchURLEndpointKeyID in ResourceEndpoints using @VM setting ResourcePos then
ResourceArray = ResourceList<ResourcePos>
Convert @VM to @FM in ResourceArray
NameProperty = ResourceArray<3>
ClassProperty = ResourceArray<5>
OtherProperties = ResourceArray<19>
Convert @SVM to @FM in OtherProperties
Convert @TM to @VM in OtherProperties
ResourceList = 'NAME' : @VM : NameProperty : @FM : 'CLASS' : @VM : ClassProperty : @FM : OtherProperties
Resource = SRP_Array('Rotate', ResourceList, @FM, @VM)
Memory_Services('SetValue', ServiceKeyID, Resource, CacheName$)
end
end
end
Response = Resource
end service
//----------------------------------------------------------------------------------------------------------------------
// SetResource
//
// URLEndpoint - URL endpoint for the resource. If empty, the APIROOT resource will be returned. - [Optional]
// PropertyArray - An @FM/@VM delimited array of resource property names and values for the resource. - [Required]
//
// Updates the array of resource property names and values for the indicated URL endpoint. Note, this replaces the
// existing property names and values. Other services should be used to update an existing array and then call this
// service when the array is updated. The PropertyArray must have at least one property name and value.
//----------------------------------------------------------------------------------------------------------------------
Service SetResource(URLEndpoint, PropertyArray)
If PropertyArray NE '' then
URLEndpointKeyID = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint, True$)
ResourceList = HTTP_Resource_Manager_Services('GetResourceList')
If Error_Services('NoError') then
ResourceArray = SRP_Array('Rotate', ResourceList, @FM , @VM)
MatchURLEndpointKeyID = URLEndpointKeyID
Convert @Upper_Case to @Lower_Case in MatchURLEndpointKeyID
ResourceEndpoints = ResourceArray<2>
Convert @Upper_Case to @Lower_Case in ResourceEndpoints
Locate MatchURLEndpointKeyID in ResourceEndpoints By 'AL' using @VM setting ResourcePos then
// This is an existing resource so update it.
Resource = ResourceList<ResourcePos>
Convert @VM to @FM in Resource
end else
// This is a new resource.
ResourceList = Insert(ResourceList, ResourcePos, 0, 0, '')
GoSub GetResourceTemplate
end
// Update the resource array with the property array data.
PropertyNames = PropertyArray<1>
PropertyValues = PropertyArray<2>
Locate 'NAME' in PropertyNames using @VM setting PropertyPos then
Name = PropertyValues<0, PropertyPos>
PropertyNames = Delete(PropertyNames, 0, PropertyPos, 0)
PropertyValues = Delete(PropertyValues, 0, PropertyPos, 0)
end else
// If no Name is provided, use the final segment of the URL endpoint.
Name = URLEndpointKeyID[-1, 'B/']
PropertyArray = Insert(PropertyArray, 1, 1, 0, 'NAME')
PropertyArray = Insert(PropertyArray, 2, 1, 0, Name)
end
Locate 'CLASS' in PropertyNames using @VM setting PropertyPos then
Class = PropertyValues<0, PropertyPos>
Locate Class in 'RESOURCE,RESOURCE_ID,PROPERTY' using ',' setting ClassPos else
Class = 'RESOURCE'
PropertyArray<2, PropertyPos> = Class
end
PropertyNames = Delete(PropertyNames, 0, PropertyPos, 0)
PropertyValues = Delete(PropertyValues, 0, PropertyPos, 0)
end else
// All resources are required to have a class. If none is specified then set it to 'RESOURCE'.
Class = 'RESOURCE'
PropertyArray = Insert(PropertyArray, 1, 1, 0, 'CLASS')
PropertyArray = Insert(PropertyArray, 2, 1, 0, Class)
end
Memory_Services('SetValue', ServiceModule : '*GetResource*' : URLEndpointKeyID, PropertyArray, CacheName$)
Resource<03> = Name
Resource<05> = Class
OtherProperties = PropertyNames : @FM : PropertyValues
OtherPropertiesList = SRP_Array('Rotate', OtherProperties, @FM, @VM)
Convert @VM to @TM in OtherPropertiesList
Convert @FM to @SVM in OtherPropertiesList
Resource<19> = OtherPropertiesList
Convert @FM to @VM in Resource
ResourceList<ResourcePos> = Resource
ResourcesKeyID = HTTP_Services('GetLocalAppKeyID', ResourcesKeyID$)
Database_Services('WriteDataRow', SetupTable$, ResourcesKeyID, ResourceList, True$, False$, True$)
end
end else
Error_Services('Add', 'PropertyArray was missing from the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// IsValidEndpoint
//
// URLEndpoint - URL endpoint for the resource. If empty, a False value will be returned. - [Required]
//
// Returns a Boolean flag indicating if the indicated URL endpoint exists.
//----------------------------------------------------------------------------------------------------------------------
Service IsValidEndpoint(URLEndpoint)
IsValidEndpoint = False$ ; // Assume False for now.
If URLEndpoint NE '' then
URLEndpointKeyID = HTTP_Resource_Manager_Services('GetEndpointResourceKeyID', URLEndpoint)
If URLEndpointKeyID NE '' then IsValidEndpoint = True$
end else
Error_Services('Add', 'URLEndpoint argument was missing in the ' : Service : ' service.')
end
Response = IsValidEndpoint
end service
//----------------------------------------------------------------------------------------------------------------------
// GetResourceList
//
// Returns the resource list for the current application.
//----------------------------------------------------------------------------------------------------------------------
Service GetResourceList()
ResourceList = ''
ResourcesKeyID = HTTP_Services('GetLocalAppKeyID', ResourcesKeyID$)
If Error_Services('NoError') then
ResourceList = Database_Services('ReadDataRow', SetupTable$, ResourcesKeyID, True$, CacheTTL$, False$)
end
Response = ResourceList
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// GetResourceTemplate
//
// Returns a template for a new resource. Most of this information is needed for the NDW_HTTP_FRAMEWORK_SETUP form's
// Tree control.
//----------------------------------------------------------------------------------------------------------------------
GetResourceTemplate:
Resource = ''
Resource<01> = DCount(URLEndpointKeyID, '/')
Resource<02> = URLEndpointKeyID
Resource<03> = URLEndpointKeyID[-1, 'B/']
Resource<04> = 'Text' : @SVM
Resource<05> = ''
Resource<06> = ''
Resource<07> = 'RGB{68, 68, 68}' : @SVM : 'White'
Resource<08> = 'Segoe UI' : @SVM : '-12' : @SVM : '400' : @SVM : '0' : @SVM : '0' : @SVM : '0' : @SVM : '1' : @SVM : '0' : @SVM : '0' : @SVM : '0' : @SVM : '0' : @SVM : '0'
Resource<09> = 'Left' : @SVM : 'Center'
Resource<10> = 'N'
Resource<11> = 'None'
Resource<12> = 1
Resource<13> = 24
Resource<14> = 0
Resource<15> = 1
Resource<16> = 'None'
Resource<17> = 'Left'
Resource<18> = 13 : @SVM : 13
return

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,256 @@
Function HTTP_Users_Services(RemainingURL)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Users_Services
Description : Handler program for the HTTP Users service module.
Notes : All HTTP web services should include the HTTP_SERVICE_SETUP insert. This will provide several useful
variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
SelfURL - The URL path representing the current service.
FullEndPointURL - The URL submitted by the client. This can be the same or longer than
the SelfURL.
NextSegment - The URL segment immediately following the SelfURL (if any). This
could contain the name of the next service or it could contain the
Item ID for the current service (aka resource).
CurrentServiceHandler - The name of this stored procedure.
Parameters :
RemainingURL [in] -- The remaining portion of the URL that follows the URL that launched this current
service. This information is used in the HTTP_SERVICE_SETUP insert to populate other
useful variables (see Notes above).
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
04/17/15 dmb Original programmer. - [SRPFW-94]
05/22/15 dmb Retrofit using the new template from HTTP_Contacts_Services and relying upon the
HTTP_Resources_Services module. - [SRPFW-94]
03/09/16 dmb Refactor to use the updated RunHTTPService service. - [SRPFW-112]
07/01/17 dmb Refactor using Enhanced BASIC+ syntax. - [SRPFW-184]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_SERVICE_SETUP
$insert HTTP_INSERTS
// Assume the current HTTP method is valid until proven otherwise.
ValidMethod = True$
// Assume the current web service is valid until provent otherwise.
ValidService = True$
// Assume no HTTP methods are valid until proven otherwise.
AllowedMethods = ''
// A list of all services able to be called from this URL.
AllowedServices = ''
// Some methods are restricted to authorized users only. Get their security level for cross-checking later.
Username = Memory_Services('GetValue', 'Username')
Security = Xlate('USERS', Username, 'ACCESS_LEVEL', 'X')
// Handle the HTTP request as needed.
Begin Case
Case RemainingURL _EQC ''
// This means the URL ends with /users, which means this is the end point. The client is requesting a
// collection of all users.
AllowedMethods = 'POST,GET,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub Post, Get, Options
end else
ValidMethod = False$
end
Case Count(RemainingURL, '/') EQ 0
// This means the URL ends with /users/{KeyID}. The client is requesting a specific user item.
AllowedMethods = 'PUT,GET,DELETE,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub PutItem, GetItem, DeleteItem, OptionsItem
end else
ValidMethod = False$
end
Case Otherwise$
ValidService = False$
End Case
// Resolve any invalid conditions with the HTTP request.
Begin Case
Case Not(ValidService)
HTTP_Services('SetResponseStatus', 404, NextSegment : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
Case Not(ValidMethod)
HTTP_Services('SetResponseStatus', 405, HTTPMethod : ' is not valid for this service.')
GoSub SetAllowedMethods
End Case
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Web Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// Post
//
// Attempts to create a new user.
//----------------------------------------------------------------------------------------------------------------------
Post:
HTTP_Resource_Services('PostDatabaseItem', 'USERS', SelfURL)
return
//----------------------------------------------------------------------------------------------------------------------
// Get
//
// Returns a collection of users. This URL also supports the passing in of query parameters, which in this case will
// will only support "name" as the query param field.
//----------------------------------------------------------------------------------------------------------------------
Get:
HAL = '' ; // Initialize the response.
If HTTP_Services('GetHTTPGetString') NE '' then
// This means the URL ends with /users?name={value}.
NameSearch = HTTP_Services('GetQueryField', 'name')
Filter = 'SELECT USERS BY USERNAME WITH USERNAME CONTAINING ' : Quote(NameSearch)
ColumnNames = 'first_name' : @FM : 'last_name'
HAL = HTTP_Resource_Services('GetDatabaseItems', Filter, 'USERS', SelfURL, ColumnNames)
end else
// This means the URL ends with /users. The client is requesting all users available at this URL.
Filter = ''
ColumnNames = 'first_name' : @FM : 'last_name'
HAL = HTTP_Resource_Services('GetDatabaseItems', Filter, 'USERS', SelfURL, ColumnNames)
end
Response = HAL
return
//----------------------------------------------------------------------------------------------------------------------
// Options
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
Options:
GoSub SetCommonOptionResponseHeaders
return
//----------------------------------------------------------------------------------------------------------------------
// PutItem
//
// Attempts to update a user. If the user does not already exist then a new one will be created.
//----------------------------------------------------------------------------------------------------------------------
PutItem:
KeyID = NextSegment
HTTP_Resource_Services('PutDatabaseItem', 'USERS', SelfURL : '/' : KeyID, KeyID)
return
//----------------------------------------------------------------------------------------------------------------------
// GetItem
//
// Returns the specific user.
//----------------------------------------------------------------------------------------------------------------------
GetItem:
KeyID = NextSegment
ColumnNames = 'first_name' : @FM : 'last_name'
HAL = HTTP_Resource_Services('GetDatabaseItem', 'USERS', SelfURL : '/' : KeyID, KeyID, ColumnNames)
Response = HAL
return
//----------------------------------------------------------------------------------------------------------------------
// DeleteItem
//
// Attempts to delete the user.
//----------------------------------------------------------------------------------------------------------------------
DeleteItem:
KeyID = NextSegment
HTTP_Resource_Services('DeleteDatabaseItem', 'USERS', KeyID)
return
//----------------------------------------------------------------------------------------------------------------------
// OptionsItem
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
OptionsItem:
GoSub SetCommonOptionResponseHeaders
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SetCommonOptionResponseHeaders
//
// Sets the response headers that will be common for all OPTIONS methods.
//----------------------------------------------------------------------------------------------------------------------
SetCommonOptionResponseHeaders:
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'x-authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Max-Age', 1728000)
GoSub SetAllowedMethods
return
//----------------------------------------------------------------------------------------------------------------------
// SetAllowedMethods
//
// Sets the Allow response header field as appropriate for the requested URL.
//----------------------------------------------------------------------------------------------------------------------
SetAllowedMethods:
If AllowedMethods NE '' then
For Each Method in AllowedMethods using ','
HTTP_Services('SetResponseHeaderField', 'Allow', Method, True$)
Next Method
end
return

View File

@ -0,0 +1,162 @@
Function HTTP_Version_Services(RemainingURL)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Version_Services
Description : Handler program for the HTTP Version service module.
Notes : All HTTP web services should include the HTTP_SERVICE_SETUP insert. This will provide several useful
variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
SelfURL - The URL path representing the current service.
FullEndPointURL - The URL submitted by the client. This can be the same or longer than
the SelfURL.
NextSegment - The URL segment immediately following the SelfURL (if any). This
could contain the name of the next service or it could contain the
Item ID for the current service (aka resource).
CurrentServiceHandler - The name of this stored procedure.
Parameters :
RemainingURL [in] -- The remaining portion of the URL that follows the URL that launched this current
service. This information is used in the HTTP_SERVICE_SETUP insert to populate other
useful variables (see Notes above).
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
07/10/17 dmb Original programmer. - [SRPFW-188]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_SERVICE_SETUP
$insert HTTP_INSERTS
// Assume the current HTTP method is valid until proven otherwise.
ValidMethod = True$
// Assume the current web service is valid until provent otherwise.
ValidService = True$
// Assume no HTTP methods are valid until proven otherwise.
AllowedMethods = ''
// A list of all services able to be called from this URL.
AllowedServices = ''
// Handle the HTTP request as needed.
Begin Case
Case RemainingURL _EQC ''
// This means the URL ends with /version.
AllowedMethods = 'GET,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub Get, Options
end else
ValidMethod = False$
end
Case Otherwise$
ValidService = False$
End Case
// Resolve any invalid conditions with the HTTP request.
Begin Case
Case Not(ValidService)
HTTP_Services('SetResponseStatus', 404, NextSegment : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
Case Not(ValidMethod)
HTTP_Services('SetResponseStatus', 405, HTTPMethod : ' is not valid for this service.')
GoSub SetAllowedMethods
End Case
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Web Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// Get
//
// Returns the version resource.
//----------------------------------------------------------------------------------------------------------------------
Get:
Version = HTTP_Services('GetVersion')
If Error_Services('NoError') then
Swap CRLF$ with @FM in Version
If SRP_JSON(hVersionObj, 'NEW', 'OBJECT') then
SRP_JSON(hVersionObj, 'SETVALUE', 'Version', Version<1>)
SRP_JSON(hVersionObj, 'SETVALUE', 'Date', Field(Version<2>, ' ', 1, 1))
SRP_JSON(hVersionObj, 'SETVALUE', 'Time', Field(Version<2>, ' ', 2, 1))
VersionBody = SRP_JSON(hVersionObj, 'STRINGIFY', 'STYLED')
SRP_JSON(hVersionObj, 'RELEASE')
HTTP_Services('SetResponseStatus', 200)
HTTP_Services('SetResponseBody', VersionBody, False, 'application/json')
end
end
return
//----------------------------------------------------------------------------------------------------------------------
// Options
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
Options:
GoSub SetCommonOptionResponseHeaders
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SetCommonOptionResponseHeaders
//
// Sets the response headers that will be common for all OPTIONS methods.
//----------------------------------------------------------------------------------------------------------------------
SetCommonOptionResponseHeaders:
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'x-authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Max-Age', 1728000)
GoSub SetAllowedMethods
return
//----------------------------------------------------------------------------------------------------------------------
// SetAllowedMethods
//
// Sets the Allow response header field as appropriate for the requested URL.
//----------------------------------------------------------------------------------------------------------------------
SetAllowedMethods:
If AllowedMethods NE '' then
For Each Method in AllowedMethods using ','
HTTP_Services('SetResponseHeaderField', 'Allow', Method, True$)
Next Method
end
return

View File

@ -0,0 +1,251 @@
Function HTTP_WebAccounts_Services(RemainingURL)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_WebAccounts_Services
Description : Handler program for the HTTP WebAccounts service module.
Notes : All HTTP web services should include the HTTP_SERVICE_SETUP insert. This will provide several useful
variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
SelfURL - The URL path representing the current service.
FullEndPointURL - The URL submitted by the client. This can be the same or longer than
the SelfURL.
NextSegment - The URL segment immediately following the SelfURL (if any). This
could contain the name of the next service or it could contain the
Item ID for the current service (aka resource).
CurrentServiceHandler - The name of this stored procedure.
Parameters :
RemainingURL [in] -- The remaining portion of the URL that follows the URL that launched this current
service. This information is used in the HTTP_SERVICE_SETUP insert to populate other
useful variables (see Notes above).
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
10/12/18 dmb Original programmer. - [SRPFW-254]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert HTTP_SERVICE_SETUP
$insert HTTP_INSERTS
Declare subroutine WebAccounts_Services, HTTP_Authentication_Services
Declare function WebAccounts_Services, HTTP_Authentication_Services
// Assume the current HTTP method is valid until proven otherwise.
ValidMethod = True$
// Assume the current web service is valid until provent otherwise.
ValidService = True$
// Assume no HTTP methods are valid until proven otherwise.
AllowedMethods = ''
// A list of all services able to be called from this URL.
AllowedServices = 'password'
AuthenticatedAccountID = HTTP_Authentication_Services('GetAuthenticatedAccountID')
// Handle the HTTP request as needed.
Begin Case
Case Count(RemainingURL, '/') GE 1
// This means the URL ends with /webaccounts/{KeyID}/{property}.
Property = FullEndPointURL[-1, 'B/']
Locate Property in AllowedServices using ',' setting ServicePos then
AllowedMethods = 'PATCH,GET,OPTIONS'
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
On MethodPos GoSub PatchItemProperty, GetItemProperty, OptionsItemProperty
end else
ValidMethod = False$
end
end else
ValidService = False$
end
Case Otherwise$
ValidService = False$
End Case
// Resolve any invalid conditions with the HTTP request.
Begin Case
Case Not(ValidService)
HTTP_Services('SetResponseStatus', 404, NextSegment : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
Case Not(ValidMethod)
HTTP_Services('SetResponseStatus', 405, HTTPMethod : ' is not valid for this service.')
GoSub SetAllowedMethods
End Case
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Web Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// PatchItemProperty
//
// Attempts to update the property of a specific resource.
//----------------------------------------------------------------------------------------------------------------------
PatchItemProperty:
// Get the name of the property by looking at the last segment in the FullEndPointURL variable. An assumption is
// being made that there are no other segments in the URL that follow the property name.
Property = FullEndPointURL[-1, 'B/']
If Property _EQC 'password' then
AccountID = NextSegment
If AccountID EQ AuthenticatedAccountID then
Password = HTTP_Authentication_Services('GetWebAccountPassword', AccountID, False$)
Body = HTTP_Services('GetHTTPPostString')
Body = HTTP_Services('DecodePercentString', Body)
If SRP_JSON(objJSON, 'Parse', Body) EQ '' then
NewPassword = SRP_JSON(objJSON, 'GetValue', 'value')
SRP_JSON(objJSON, 'Release')
HTTP_Authentication_Services('SetWebAccountPassword', AccountID, Password, NewPassword)
If Error_Services('NoError') then
If SRP_JSON(objJSON, 'New', 'Object') then
If SRP_JSON(objLinks, 'New', 'Object') then
If SRP_JSON(objSelf, 'New', 'Object') then
SRP_JSON(objSelf, 'SetValue', 'href', FullEndPointURL)
SRP_JSON(objLinks, 'Set', 'self', objSelf)
SRP_JSON(objSelf, 'Release')
end
SRP_JSON(objJSON, 'Set', '_links', objLinks)
SRP_JSON(objLinks, 'Release')
end
SRP_JSON(objJSON, 'SetValue', 'value', NewPassword, 'String')
HAL = SRP_JSON(objJSON, 'Stringify', 'Fast')
SRP_JSON(objJSON, 'Release')
HTTP_Services('SetResponseBody', HAL, False$, 'application/hal+json')
end
end else
HTTP_Services('SetResponseStatus', '403', Error_Services('GetMessage'))
end
end else
Error_Services('Add', 'Error parsing JSON body within the ' : CurrentServiceHandler : ' module.')
HTTP_Services('SetResponseStatus', '500', Error_Services('GetMessage'))
end
end else
HTTP_Services('SetResponseStatus', '401', 'This account is not authorized for this endpoint.')
end
end else
// The URL contains an unsupported property. Return a 404 error.
HTTP_Services('SetResponseStatus', 404, Property : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// GetItemProperty
//
// Returns the property of a specific resource.
//----------------------------------------------------------------------------------------------------------------------
GetItemProperty:
// Get the name of the property by looking at the last segment in the FullEndPointURL variable. An assumption is
// being made that there are no other segments in the URL that follow the property name.
Property = FullEndPointURL[-1, 'B/']
If Property _EQC 'password' then
AccountID = NextSegment
If AccountID EQ AuthenticatedAccountID then
Password = HTTP_Authentication_Services('GetWebAccountPassword', AccountID, False$)
jsonWebAccounts = WebAccounts_Services('GetWebAccounts', AccountID, True$)
If Error_Services('NoError') then
If SRP_JSON(objJSON, 'Parse', jsonWebAccounts) EQ '' then
objPassword = SRP_JSON(objJSON, 'Get', 'password')
SRP_JSON(objJSON, 'Release')
If SRP_JSON(objLinks, 'New', 'Object') then
If SRP_JSON(objSelf, 'New', 'Object') then
SRP_JSON(objSelf, 'SetValue', 'href', FullEndPointURL)
SRP_JSON(objLinks, 'Set', 'self', objSelf)
SRP_JSON(objSelf, 'Release')
end
SRP_JSON(objPassword, 'Set', '_links', objLinks)
SRP_JSON(objLinks, 'Release')
end
HAL = SRP_JSON(objPassword, 'Stringify', 'Fast')
SRP_JSON(objPassword, 'Release')
HTTP_Services('SetResponseBody', HAL, False$, 'application/hal+json')
end else
Error_Services('Add', 'Error parsing JSON body within the ' : CurrentServiceHandler : ' module.')
HTTP_Services('SetResponseStatus', '500', Error_Services('GetMessage'))
end
end else
HTTP_Services('SetResponseStatus', '403', Error_Services('GetMessage'))
end
end else
HTTP_Services('SetResponseStatus', '401', 'This account is not authorized for this endpoint.')
end
end else
// The URL contains an unsupported property. Return a 404 error.
HTTP_Services('SetResponseStatus', 404, Property : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
end
return
//----------------------------------------------------------------------------------------------------------------------
// OptionsItemProperty
//
// Sets the appropriate response header fields for an OPTIONS request.
//----------------------------------------------------------------------------------------------------------------------
OptionsItemProperty:
GoSub SetCommonOptionResponseHeaders
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// SetCommonOptionResponseHeaders
//
// Sets the response headers that will be common for all OPTIONS methods.
//----------------------------------------------------------------------------------------------------------------------
SetCommonOptionResponseHeaders:
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'x-authorization', True$)
HTTP_Services('SetResponseHeaderField', 'Access-Control-Max-Age', 1728000)
GoSub SetAllowedMethods
return
//----------------------------------------------------------------------------------------------------------------------
// SetAllowedMethods
//
// Sets the Allow response header field as appropriate for the requested URL.
//----------------------------------------------------------------------------------------------------------------------
SetAllowedMethods:
If AllowedMethods NE '' then
For Each Method in AllowedMethods using ','
HTTP_Services('SetResponseHeaderField', 'Allow', Method, True$)
Next Method
end
return

View File

@ -0,0 +1,506 @@
Function Logging_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Logging_Services
Description : Handler program for all module related services.
Notes : The generic parameters should contain all the necessary information to process the services. Often
this will be information like the data Record and Key ID.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
08/30/17 dmb Original programmer.
02/17/18 dmb Use the new named cache feature of Memory_Services so logging data is protected when other
processes release a cache table.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
$insert SRPMail_Inserts
Equ CRLF$ to \0D0A\
Equ CR$ to \0D\
Equ LF$ to \0A\
Equ TAB$ to \09\
Equ COMMA$ to ','
Common /LogginServices/ Unused1@, Unused2@, Unused3@, Unused4@, Unused5@, Unused6@, Unused7@, Unused8@
Declare function Logging_Services, Memory_Services, SRP_Hash, SRP_Path, SRP_Send_Mail, Environment_Services
Declare subroutine Logging_Services, Memory_Services, SetInitDirOptions
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the Logging services module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// NewLog
//
// LogPath - Path to where the log file is located. - [Required]
// LogFileName - Name of the log file. - [Required]
// RowDelimiter - Delimiter used to separate each log row. Default is CR/LF. - [Optional]
// ColumnDelimiter - Delimiter used to separate each column value. If ColumnWidths is empty then this will default to a
// comma. - [Optional]
// ColumnHeaders - @FM list of Column headers to use in the log file. Default is no column headers will be used.
// - [Optional]
// ColumnWidths - @FM list of Column widths for each column data value. If empty then the entire column value will
// be stored. - [Optional]
// QuoteValues - Boolean flag to indicate if column values should be quoted. Default is false. - [Optional]
// ClearLog - Boolean flag to indicate if any existing log file should be cleared. Default is false.
// - [Optional]
//
// Returns an object handle to a log file.
//----------------------------------------------------------------------------------------------------------------------
Service NewLog(LogPath, LogFileName, RowDelimiter, ColumnDelimiter, ColumnHeaders, ColumnWidths, QuoteValues=BOOLEAN, ClearLog=BOOLEAN)
objLog = ''
If (LogPath NE '') AND (LogFileName NE '') then
If SRP_Path('Exists', LogPath) then
LogFullPath = SRP_Path('Combine', LogPath, LogFileName)
If LogFullPath[1, 1] EQ '\' AND LogFullPath[2, 1] NE '\' then LogFullPath = '\' : LogFullPath
objLog = SRP_Hash(LogFullPath, 'SHA-1', 'BASE32')
Memory_Services('SetValue', objLog : '*LogPath', LogPath, ServiceModule)
Memory_Services('SetValue', objLog : '*LogFileName', LogFileName, ServiceModule)
Memory_Services('SetValue', objLog : '*LogFullPath', LogFullPath, ServiceModule)
If Dir(LogFullPath) NE '' then
If ClearLog then
Logging_Services('CreateLogFile', objLog)
end
end else
Logging_Services('CreateLogFile', objLog)
end
If Error_Services('NoError') then
If RowDelimiter EQ '' then RowDelimiter = CRLF$
Memory_Services('SetValue', objLog : '*RowDelimiter', RowDelimiter, ServiceModule)
If (ColumnDelimiter EQ '') AND (ColumnWidths EQ '') then ColumnDelimiter = COMMA$
Memory_Services('SetValue', objLog : '*ColumnDelimiter', ColumnDelimiter, ServiceModule)
Memory_Services('SetValue', objLog : '*ColumnHeaders', ColumnHeaders, ServiceModule)
Memory_Services('SetValue', objLog : '*ColumnWidths', ColumnWidths, ServiceModule)
If QuoteValues NE True$ then QuoteValues = False$
Memory_Services('SetValue', objLog : '*QuoteValues', QuoteValues, ServiceModule)
If Dir(LogFullPath)<1> EQ 0 AND ColumnHeaders NE '' then
// Add the column headers since this is a new log file.
Logging_Services('AppendLog', objLog, ColumnHeaders, '', @FM, True$)
end
end
end else
Error_Services('Add', LogPath : ' does not exist.')
end
end else
Error_Services('Add', 'LogPath or LogFileName argument was missing from the ' : Service : ' service.')
end
Response = objLog
end service
//----------------------------------------------------------------------------------------------------------------------
// AppendLog
//
// objLog - Object handle to the log file. - [Required]
// LogData - Data to be appended to the log file. - [Required]
// IncomingRowDelimiter - Delimiter used to separate each log row coming in. This allows incoming log data to have
// a different delimiter than what will be used in the log file. Default is the RowDelimiter
// used for appending the log data. - [Optional]
// IncomingColumnDelimiter - Delimiter used to separate each column value in the log data. This allows incoming log
// data to have a different delimiter than what will be used in the log file. Default is the
// column delimiter used to separate the log data or a comma if fixed widths only are
// indicated. - [Optional]
// IgnoreColumnHeaders - Boolean flag to indicate if the service should attempt to add column headers to an empty
// log file. Default is false. - [Optional]
// EmailAddresses - Comma delimited list of email addresses that should be notified when this log is appended.
// - [Optional]
// EmailMessage - Message to be sent to the email addresses.
//
// Appends data to the log file associated with the indicated log object handle.
//----------------------------------------------------------------------------------------------------------------------
Service AppendLog(objLog, LogData, IncomingRowDelimiter, IncomingColumnDelimiter, IgnoreColumnHeaders, EmailAddresses, EmailMessage)
If (objLog NE '') AND (LogData NE '') then
If IgnoreColumnHeaders NE True$ then IgnoreColumnHeaders = False$
LogFullPath = Logging_Services('GetLogFullPath', objLog)
ColumnDelimiter = Logging_Services('GetColumnDelimiter', objLog)
LenColDel = Len(ColumnDelimiter)
ColumnHeaders = Logging_Services('GetColumnHeaders', objLog)
ColumnWidths = Logging_Services('GetColumnWidths', objLog)
QuoteValues = Logging_Services('GetQuoteValues', objLog)
RowDelimiter = Logging_Services('GetRowDelimiter', objLog)
If IncomingRowDelimiter EQ '' then IncomingRowDelimiter = RowDelimiter
If (IncomingColumnDelimiter EQ '') AND (ColumnWidths EQ '') then IncomingColumnDelimiter = ColumnDelimiter
LenRowDel = Len(RowDelimiter)
FileInfo = Dir(LogFullPath)
FileSize = FileInfo<1>
Status() = 0
OutData = ''
OSOpen LogFullPath to hFile then
If (FileSize EQ 0) AND (ColumnHeaders NE '') AND (Not(IgnoreColumnHeaders)) then
Logging_Services('AppendLog', objLog, ColumnHeaders, @RM, @FM, True$)
end
For Each RowData in LogData using IncomingRowDelimiter
If RowData NE '' then
For Each ColumnData in RowData using IncomingColumnDelimiter setting cPos
If ColumnWidths NE '' then
ColumnWidth = ColumnWidths<cPos>
ColumnData = ColumnData[1, ColumnWidth] : Str(' ', ColumnWidth - Len(ColumnData))
end
If QuoteValues then
Swap '"' with '""' in ColumnData ; // Encode the quotes properly.
ColumnData = Quote(ColumnData)
end
OutData := ColumnData : ColumnDelimiter
Next ColumnData
OutData[Neg(LenColDel), LenColDel] = '' ; // Strip off the last column delimiter.
OutData := RowDelimiter ; // Append a row delimiter.
end
Next LogRow
OutData[Neg(LenRowDel), LenRowDel] = '' ; // Strip off the last row delimiter.
If (FileSize NE 0) then OutData = RowDelimiter : OutData ; // Prepend a row delimiter since there is existing data.
OSBWrite OutData to hFile at FileSize
OSError = Status()
If OSError then
Error_Services('Add', 'OSBWrite error code ' : OSError : ' in the ' : Service : ' service.')
end
OSClose hFile
end else
OSError = Status()
Error_Services('Add', 'OSOpen error code ' : OSError : ' in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
If EmailAddresses NE '' then
GoSub EmailMessage
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetLogPath
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the path for the log file associated with the indicated log object handle. This will not include the name of
// the log file itself.
//----------------------------------------------------------------------------------------------------------------------
Service GetLogPath(objLog)
LogPath = ''
If objLog NE '' then
LogPath = Memory_Services('GetValue', objLog : '*LogPath', '', '', ServiceModule)
If LogPath EQ '' then
Error_Services('Add', 'Log path not found in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = LogPath
end service
//----------------------------------------------------------------------------------------------------------------------
// GetLogFileName
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the file name for the log file associated with the indicated log object handle. This will not include the
// path to where the log file is located.
//----------------------------------------------------------------------------------------------------------------------
Service GetLogFileName(objLog)
LogFileName = ''
If objLog NE '' then
LogFileName = Memory_Services('GetValue', objLog : '*LogFileName', '', '', ServiceModule)
If LogFileName EQ '' then
Error_Services('Add', 'Log file name not found in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = LogFileName
end service
//----------------------------------------------------------------------------------------------------------------------
// GetLogFullPath
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the full path for the log file associated with the indicated log object handle.
//----------------------------------------------------------------------------------------------------------------------
Service GetLogFullPath(objLog)
LogFullPath = ''
If objLog NE '' then
LogFullPath = Memory_Services('GetValue', objLog : '*LogFullPath', '', '', ServiceModule)
If LogFullPath EQ '' then
Error_Services('Add', 'Log full path not found in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = LogFullPath
end service
//----------------------------------------------------------------------------------------------------------------------
// GetRowDelimiter
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the delimiter to use to separate each row in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetRowDelimiter(objLog)
RowDelimiter = ''
If objLog NE '' then
RowDelimiter = Memory_Services('GetValue', objLog : '*RowDelimiter', '', '', ServiceModule)
If RowDelimiter EQ '' then
Error_Services('Add', 'Row delimiter not found in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = RowDelimiter
end service
//----------------------------------------------------------------------------------------------------------------------
// GetColumnDelimiter
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the delimiter to use to separate each column in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetColumnDelimiter(objLog)
ColumnDelimiter = ''
If objLog NE '' then
ColumnDelimiter = Memory_Services('GetValue', objLog : '*ColumnDelimiter', '', '', ServiceModule)
If ColumnDelimiter EQ '' then
Error_Services('Add', 'Column delimiter not found in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = ColumnDelimiter
end service
//----------------------------------------------------------------------------------------------------------------------
// GetColumnHeaders
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the column headers that should be in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetColumnHeaders(objLog)
ColumnHeaders = ''
If objLog NE '' then
ColumnHeaders = Memory_Services('GetValue', objLog : '*ColumnHeaders', '', '', ServiceModule)
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = ColumnHeaders
end service
//----------------------------------------------------------------------------------------------------------------------
// GetColumnWidths
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the column widths that should be used to truncate or pad each column in the log.
//----------------------------------------------------------------------------------------------------------------------
Service GetColumnWidths(objLog)
ColumnWidths = ''
If objLog NE '' then
ColumnWidths = Memory_Services('GetValue', objLog : '*ColumnWidths', '', '', ServiceModule)
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = ColumnWidths
end service
//----------------------------------------------------------------------------------------------------------------------
// GetQuoteValues
//
// objLog - Object handle to the log file. - [Required]
//
// Returns the flag to indicate whether column values should be quoted or not.
//----------------------------------------------------------------------------------------------------------------------
Service GetQuoteValues(objLog)
QuoteValues = ''
If objLog NE '' then
QuoteValues = Memory_Services('GetValue', objLog : '*QuoteValues', '', '', ServiceModule)
If QuoteValues NE True$ then QuoteValues = False$
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
Response = QuoteValues
end service
//----------------------------------------------------------------------------------------------------------------------
// CreateLogFile
//
// objLog - Object handle to the log file. - [Required]
//
// Creates (or clears out) a log file associated with the indicated log object handle.
//----------------------------------------------------------------------------------------------------------------------
Service CreateLogFile(objLog)
If objLog NE '' then
LogFullPath = Logging_Services('GetLogFullPath', objLog)
If Error_Services('NoError') then
Status() = 0
OSWrite '' to LogFullPath
Status = Status()
If Status GT 0 then
Error_Services('Add', 'Unable to clear ' : LogFullPath : ' in the ' : Service : ' service.')
end
end
end else
Error_Services('Add', 'objLog argument was missing from the ' : Service : ' service.')
end
end service
Service CleanLogFolders(NumDays)
FileExclusionList = 'Canary.txt':@VM:'Canary.vbs'
AppRootPath = Environment_Services('GetApplicationRootPath')
LogPath = AppRootPath : '\LogFiles\'
SetInitDirOptions("D")
InitDir LogPath:'*'
FolderList = DirList()
// Remove . directory listing
FolderList = Delete(FolderList, 1, 0, 0)
// Remove .. directory listing
FolderList = Delete(FolderList, 1, 0, 0)
Today = Date()
SetInitDirOptions("")
For each Folder in FolderList
FolderPath = LogPath:Folder:'\'
InitDir FolderPath:'*'
FileList = DirList()
If FileList NE '' then
For each Filename in FileList
Locate FileName in FileExclusionList using @VM setting vPos else
FilePath = FolderPath:Filename
FileInfo = Dir(FilePath)
LastWriteDate = FileInfo<2>
FileAge = Today - LastWriteDate
If FileAge GT NumDays then
OSDelete FilePath
end
end
Next Filename
end
Next Folder
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EmailMessage:
Done = False$
Error = False$
MsgSent = ''
ConfigFile = ''
ConfigFile<1> = SendUsing_Port$
ConfigFile<2> = ''
ConfigFile<3> = 25 ; // Server port
*ConfigFile<4> = 'appmail.eu.infineon.com' ; // Mail server
ConfigFile<4> = 'mailrelay-external.infineon.com' ; // Mail server
ConfigFile<5> = True$ ; // Authenticate
ConfigFile<6> = 'oinotify@infineon.com' ; // Username
ConfigFile<7> = 'oinotify1' ; // Password
ConfigFile<8> = False$ ; // Use SSL
If EmailMessage EQ '' then
EmailMessage = LogData : \0D0A0D0A\ : RetStack()<2>
end else
EmailMessage := \0D0A0D0A\ : LogData : \0D0A0D0A\ : RetStack()<2>
end
SentFrom = ''
SentTo = ''
Message = ''
Message<1> = 'AppendLog Message' ; // Subject
Message<2> = 'oinotify@infineon.com' ; // From (email address)
Message<3> = EmailAddresses ; // Send to (email address)
Message<5> = '' ; // Blind Carbon Copy (email address)
Message<6> = '' ; // Reply To (email address)
Message<7> = 'TEXT' ; // Content Type (TEXT or HTML)
Message<8> = EmailMessage ; // Content / Body
Message<9> = '' ; // Attachment(s) (path to file name(s))
Result = SRP_Send_Mail(Message, ConfigFile)
return

View File

@ -0,0 +1,408 @@
Function Memory_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Memory_Services
Description : Handler program for all module related services.
Notes : The generic parameters should contain all the necessary information to process the services. Often
this will be information like the data Record and Key ID.
Parameters :
Service [in] -- Name of the service being requested
Error [out] -- Any errors that were created
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
History : (Date, Initials, Notes)
03/29/13 dmb [SRPFW-9] Original programmer.
08/01/13 dmb [SRPFW-16] Add PM_CURRENT_IMAGE_PATH as an option to the GETVALUES list.
10/01/13 dmb [SRPFW-18] Replace APP_INSERTS with LOGICAL and declare Error_Services. -
10/05/13 dmb [SRPFW-18] Add the RemoveKey service.
11/06/14 dmb [SRPFW-79] Add support to tag cached data with a time marker in the SetValue service so
subsequent GetValue calls can avoid using data that might be too old.
10/29/17 dmb Retrofit to use Enhanced BASIC+.
02/17/18 dmb Add support to name specific memory service caches. This was to allow some memory service
data to be protect from the ReleaseHashTable service. All services will default to the
general cache if no cache name is specified. Added ReleaseAllHashTables to clear all caches.
09/25/19 dmb [SRPFW-278] Update all services that support named caches so that whenever the named cache
doesn't exist it will create one automatically rather than default to the primary cache.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
Common /MemoryServices/ MemoryServicesManagers@, MemoryCacheNames@, Unused3@, Unused4@, Unused5@, Unused6@
Equ Day$ to 86400 ; // Seconds in one day.
// Self referencing declarations.
Declare function Memory_Services
Declare subroutine Memory_Services, Error_Services
// SRP FastArray declarations.
Declare function SRP_FastArray_Count, SRP_FastArray_Create, SRP_FastArray_Extract, SRP_FastArray_GetVariable,
Declare subroutine SRP_FastArray_Delete, SRP_FastArray_Insert, SRP_FastArray_InsertFromList, SRP_FastArray_Release, SRP_FastArray_Replace, SRP_FastArray_ReplaceWithList
// SRP HashTable declarations.
Declare function SRP_HashTable_Create, SRP_HashTable_Contains, SRP_HashTable_Count, SRP_HashTable_Get, SRP_HashTable_GetKeys, SRP_HashTable_GetValues, SRP_HashTable_GetKeyValuePairs
Declare subroutine SRP_HashTable_Set, SRP_HashTable_Release, SRP_HashTable_Remove
// SRP List declarations.
Declare function SRP_List_Create, SRP_List_CreateFromFastArray, SRP_List_Count, SRP_List_GetAt, SRP_List_GetVariable, SRP_List_Locate
Declare subroutine SRP_List_Add, SRP_List_InsertAt, SRP_List_Release, SRP_List_RemoveAt, SRP_List_SetAt
// SRP Array declarations.
Declare function SRP_Clean_Array, SRP_Join_Arrays, SRP_Reorder_Array, SRP_Rotate_Array, SRP_Sort_Array
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// KeyExists
//
// Returns a True or False depending on whether the Key ID exists.
//----------------------------------------------------------------------------------------------------------------------
Service KeyExists(KeyID, CacheName)
KeyExists = False$ ; // Assume it does not exist for now.
If Len(KeyID) then
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
// The named cache does not exist so create it now.
Memory_Services('CreateHashTable', CacheName)
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
HandlePos = 1
end
end
end
If Len(MemoryServicesManagers@<HandlePos>) then
KeyExists = SRP_HashTable_Contains(MemoryServicesManagers@<HandlePos>, KeyID)
end
end else
Error_Services('Set', 'Key ID did not contain a value in the KeyExists service request.')
end
Response = KeyExists
end service
//----------------------------------------------------------------------------------------------------------------------
// GetValue
//
// Returns the value pair stored in the SRP Hash Table for the current Key ID. If the NotExpired flag is set, the
// ExpirationDuration will be used to compare against the last time marker set for the current data.
//----------------------------------------------------------------------------------------------------------------------
Service GetValue(KeyID, NotExpired, ExpirationDuration, CacheName)
Value = '' ; // Assume the value is null for now.
If Len(KeyID) then
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
// The named cache does not exist so create it now.
Memory_Services('CreateHashTable', CacheName)
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
HandlePos = 1
end
end
end
If Len(MemoryServicesManagers@<HandlePos>) then
If NotExpired then
CurrMarker = (Date() * Day$) + Time()
PrevMarker = SRP_HashTable_Get(MemoryServicesManagers@<HandlePos>, 'TIMEMARKER*' : KeyID)
If (CurrMarker - PrevMarker) LT ExpirationDuration then
Value = SRP_HashTable_Get(MemoryServicesManagers@<HandlePos>, KeyID)
end
end else
Value = SRP_HashTable_Get(MemoryServicesManagers@<HandlePos>, KeyID)
end
end
end else
Error_Services('Set', 'Key ID did not contain a value in the GetValue service request.')
end
Response = Value
end service
//----------------------------------------------------------------------------------------------------------------------
// SetValue
//
// Updates the value pair stored in the SRP Hash Table for the current Key ID.
//----------------------------------------------------------------------------------------------------------------------
Service SetValue(KeyID, Value, CacheName)
If Len(KeyID) then
// If the Memory Services's hash table does not yet exist then create it now.
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
// The named cache does not exist so create it now.
Memory_Services('CreateHashTable', CacheName)
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
HandlePos = 1
end
end
end
If Len(MemoryServicesManagers@<HandlePos>) else
Memory_Services('CreateHashTable', CacheName)
end
SRP_HashTable_Set(MemoryServicesManagers@<HandlePos>, KeyID, Value)
// Set a time marker for this data in case future GetValue services need to know how old the data is.
TimeMarker = (Date() * Day$) + Time()
SRP_HashTable_Set(MemoryServicesManagers@<HandlePos>, 'TIMEMARKER*' : KeyID, TimeMarker)
end else
Error_Services('Set', 'Key ID did not contain a value in the SetValue service request.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// IsValueExpired
//
// Returns a Boolean flag indicated whether the current value for the indicated KeyID has expired. This relies upon the
// time marker set using the SetValue service. If this value has net yet been set then the value will be considered as
// expired.
//----------------------------------------------------------------------------------------------------------------------
Service IsValueExpired(KeyID, ExpirationDuration, ResetAge, CacheName)
If Not(Num(ExpirationDuration)) then ExpirationDuration = 0
ValueExpired = True$ ; // Assume the value has expired for now.
If ResetAge NE True$ then ResetAge = False$ ; // Default is false unless otherwise specified.
If Len(KeyID) AND (ExpirationDuration GT 0) then
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
// The named cache does not exist so create it now.
Memory_Services('CreateHashTable', CacheName)
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
HandlePos = 1
end
end
end
If Len(MemoryServicesManagers@<HandlePos>) then
PrevMarker = SRP_HashTable_Get(MemoryServicesManagers@<HandlePos>, 'TIMEMARKER*' : KeyID)
If PrevMarker NE '' then
TimeMarker = (Date() * Day$) + Time()
If (TimeMarker - PrevMarker) LE ExpirationDuration then
ValueExpired = False$
If ResetAge EQ True$ then
SRP_HashTable_Set(MemoryServicesManagers@<HandlePos>, 'TIMEMARKER*' : KeyID, TimeMarker)
end
end
end
end
end else
Error_Services('Set', 'KeyID or ExpirationDuraton was missing in the IsValueExpired service.')
end
Response = ValueExpired
end service
//----------------------------------------------------------------------------------------------------------------------
// IsValueCurrent
//
// Returns a Boolean flag indicated whether the current value for the indicated KeyID is still current. This relies upon the
// time marker set using the SetValue service. If this value has net yet been set then the value will be considered as
// expired.
//----------------------------------------------------------------------------------------------------------------------
Service IsValueCurrent(KeyID, ExpirationDuration, ResetAge, CacheName)
If Not(Num(ExpirationDuration)) then ExpirationDuration = 0
ValueCurrent = False$ ; // Assume the value is not current for now.
If ResetAge NE True$ then ResetAge = False$ ; // Default is false unless otherwise specified.
If Len(KeyID) AND (ExpirationDuration GT 0) then
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
// The named cache does not exist so create it now.
Memory_Services('CreateHashTable', CacheName)
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
HandlePos = 1
end
end
end
If Len(MemoryServicesManagers@<HandlePos>) then
PrevMarker = SRP_HashTable_Get(MemoryServicesManagers@<HandlePos>, 'TIMEMARKER*' : KeyID)
If PrevMarker NE '' then
TimeMarker = (Date() * Day$) + Time()
If (TimeMarker - PrevMarker) LE ExpirationDuration then
ValueCurrent = True$
If ResetAge EQ True$ then
SRP_HashTable_Set(MemoryServicesManagers@<HandlePos>, 'TIMEMARKER*' : KeyID, TimeMarker)
end
end
end
end
end else
Error_Services('Set', 'KeyID or ExpirationDuraton was missing in the IsValueCurrent service.')
end
Response = ValueCurrent
end service
//----------------------------------------------------------------------------------------------------------------------
// RemoveKey
//
// Removes the Key ID, and its value pair, from the SRP Hash Table.
//----------------------------------------------------------------------------------------------------------------------
Service RemoveKey(KeyID, CacheName)
If Len(KeyID) then
// If the Memory Services's hash table does not yet exist then create it now.
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
// The named cache does not exist so create it now.
Memory_Services('CreateHashTable', CacheName)
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else
HandlePos = 1
end
end
end
If Len(MemoryServicesManagers@<HandlePos>) then
SRP_HashTable_Remove(MemoryServicesManagers@<HandlePos>, KeyID)
end
end else
Error_Services('Set', 'Key ID did not contain a value in the RemoveKey service request.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// CreateHashTable
//
// Creates the SRP Hash Table that the Memory_Services module will use to manage various Key ID and Value pairs. A
// check will first be made to see if the handle to the Hash Table already exists. If so then it will be released and
// a new Hash Table will be created.
//----------------------------------------------------------------------------------------------------------------------
Service CreateHashTable(CacheName)
If CacheName EQ '' then
HandlePos = 1
If Len(MemoryServicesManagers@<HandlePos>) then
Memory_Services('ReleaseHashTable')
end
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos then
Memory_Services('ReleaseHashTable', CacheName)
end else
HandlePos = DCount(MemoryCacheNames@, @FM) + 1
If HandlePos EQ 1 then HandlePos = 2 ; // Handle position 1 is reserved for the default cache.
end
end
MemoryServicesManagers@<HandlePos> = SRP_HashTable_Create()
If HandlePos GT 1 then
MemoryCacheNames@<HandlePos> = CacheName
end
Response = MemoryServicesManagers@<HandlePos>
end service
//----------------------------------------------------------------------------------------------------------------------
// ReleaseHashTable
//
// Releases the SRP Hash Table handle. If CacheName is empty then the default handle is released.
//----------------------------------------------------------------------------------------------------------------------
Service ReleaseHashTable(CacheName)
HandlePos = ''
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else Null
end
If HandlePos GE 1 then
SRP_HashTable_Release(MemoryServicesManagers@<HandlePos>)
MemoryServicesManagers@<HandlePos> = ''
MemoryCacheNames@<HandlePos> = ''
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ReleaseAllHashTables
//
// Releases all SRP Hash Table handles.
//----------------------------------------------------------------------------------------------------------------------
Service ReleaseAllHashTables(CacheName)
If MemoryServicesManagers@ NE '' then
For Each Handle in MemoryServicesManagers@ using @FM
If Handle NE '' then SRP_HashTable_Release(Handle)
Next Handle
end
MemoryServicesManagers@ = ''
MemoryCacheNames@ = ''
end service
//----------------------------------------------------------------------------------------------------------------------
// GetHandle
//
// Returns the handle to the SRP Hash Table used by Memory_Services.
//----------------------------------------------------------------------------------------------------------------------
Service GetHandle(CacheName)
HandlePos = ''
If CacheName EQ '' then
HandlePos = 1
end else
Locate CacheName in MemoryCacheNames@ using @FM setting HandlePos else Null
end
If HandlePos GE 1 then
Handle = MemoryServicesManagers@<HandlePos>
end
Response = Handle
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////?

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,437 @@
Function NDW_Audit_Viewer_Events(CtrlEntId, Event, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : NDW_Audit_Viewer_Events
Description : This function acts as a commuter module for all events related to this window.
Notes : Commuter Modules are automatically called from the Promoted_Events function which is called by the
application-specific promoted event handler. This makes it possible to add QuickEvents that need to
execute Basic+ logic without having use the Form Designer to make the association, although this is
limited to the events which are currently promoted.
If the form needs to call the commuter module directly then the QuickEvent parameters should be
formatted like this:
'@SELF','@EVENT',['@PARAM1','@PARAMx']
Parameters :
CtrlEntId [in] -- The fully qualified name of the control calling the promoted event
Event [in] -- The event being executed. See the Notes section regarding "PRE" events
Param1-15 [in] -- Additional event parameter holders
EventFlow [out] -- Set to 1 or 0 so the calling event knows whether or not to chain forward. See comments in
EVENT_SETUP insert
History : (Date, Initials, Notes)
07/23/98 dmb Original programmer.
03/30/06 axf Removed reference to Application.dll.
04/06/13 dmb Replace ErrorLines property with MismatchLines property for better comparison viewing.
- [SRPFW-9]
***********************************************************************************************************************/
$insert APP_INSERTS
$insert EVENT_SETUP
$insert MSG_EQUATES
Equ WM_USER$ To 1024
Equ WM_SETREADONLY$ To WM_USER$ + 31
AuditManagerTable = "APP_INFO"
Declare Subroutine Msg, Send_Event, V119, SRP_Set_Prop_Array, Utility, Start_Window, Send_Message, Get_SysInfo, SRP_Show_Window, Set_Property, Post_Event
Declare Function GetPointer, GetSystemInfo, Send_Message
Begin Case
Case Control EQ Window
// This event is window specific.
Begin Case
Case Event EQ "CREATE" ; GoSub CREATE
Case Event EQ 'EXPAND_ROW' ; GoSub EXPAND_ROW
Case Event EQ 'COLLAPSE_ROW' ; GoSub COLLAPSE_ROW
Case Event EQ 'GOTO_MARKER' ; GoSub TOGGLE_CURSOR
End Case
Case EventType EQ "CLICK"
Begin Case
Case Control EQ "PUB_RESTORE" ; GoSub CLICK.PUB_RESTORE
Case Control EQ "PUB_COMPARE" ; GoSub CLICK.PUB_COMPARE
Case Control EQ "PUB_RETURN" ; GoSub CLICK.PUB_RETURN
End Case
Case Event EQ "PosChanged" ; GoSub PosChanged
Case Event EQ "OnGotFocus" ; GoSub PosChanged
Case Event EQ "OnVScroll"
Begin Case
Case Control EQ "OLE_ARCHIVE" ; GoSub OnVScroll.OLE_ARCHIVE
Case Control EQ "OLE_ORIGINAL" ; GoSub OnVScroll.OLE_ORIGINAL
End Case
Case Event EQ 'MENU.EXPAND_ROW' ; GoSub MENU.EXPAND_ROW
Case Event EQ 'MENU.COLLAPSE_ROW' ; GoSub MENU.COLLAPSE_ROW
Case Event EQ 'MENU.NEXT_DIFFERENCE' ; GoSub MENU.NEXT_DIFFERENCE
End Case
If Assigned(EventFlow) else EventFlow = EVENT_CONTINUE$
Return EventFlow
CREATE:
// qualify editor events
Events = "PosChanged,OnGotFocus,OnVScroll"
LenEvents = Len(Events)
Pos = 1
Loop Until Pos GE LenEvents
Event = "OLE.":Events[Pos, ","]
Pos = Col2() + 1
Send_Message(@Window:".OLE_ARCHIVE", "QUALIFY_EVENT", Event, Yes$)
Send_Message(@Window:".OLE_ORIGINAL", "QUALIFY_EVENT", Event, Yes$)
Repeat
Send_Message(@Window:".OLE_VIEWER", "QUALIFY_EVENT", "PosChanged", Yes$)
// show the viewer
SRP_Show_Window(@Window, "", "L", "T", Yes$, "", No$, No$)
return
EXPAND_ROW:
*----------------------------------------------------------------------------------------------------
* Expands row(s) in the Audit Viewer Window
*----------------------------------------------------------------------------------------------------
WindowControl = Get_Property(@Window, "FOCUS")
Set_Property(WindowControl, "READONLY", No$)
rv = Send_Message(WindowControl, "OLE.ExpandCurrLine")
Set_Property(WindowControl, "READONLY", Yes$)
return
COLLAPSE_ROW:
*----------------------------------------------------------------------------------------------------
* Collapses Row(s) in the Audit Viewer Window
*----------------------------------------------------------------------------------------------------
WindowControl = Get_Property(@Window, "FOCUS")
Set_Property(WindowControl, "READONLY", No$)
rv = Send_Message(WindowControl, "OLE.CollapseCurrLine")
Set_Property(WindowControl, "READONLY", Yes$)
return
TOGGLE_CURSOR:
*----------------------------------------------------------------------------------------------------
* Toggles from marker to marker in the Audit View Window
*----------------------------------------------------------------------------------------------------
Set_Property(WindowControl, "READONLY", No$)
WindowControl = Get_Property(@Window, "FOCUS")
rv = Send_Message(WindowControl, "OLE.GoToMarker")
Set_Property(WindowControl, "READONLY", Yes$)
return
CLICK.PUB_RESTORE:
*----------------------------------------------------------------------------------------------------
*
*----------------------------------------------------------------------------------------------------
Begin Case
Case Window = "NDW_AUDIT_TRAIL"
Win$ = @Window
Case Otherwise$
Win$ = Get_Property(@Window:".EDL_WINDOW", "INVALUE")
End Case
TableName = Get_Property(Win$:".COB_TABLE", "INVALUE")
Convert @Lower_Case to @Upper_Case in TableName
rVal = Get_Property(Win$:".EDT_INFO_BAK", "ARRAY")
Convert @VM to " " in rVal
rVal = Trim(rVal)
TestVal = Count(rVal, " ")
If TestVal GT 0 Then
ErrorMsg = "TOOMANY"
Gosub MsgAlert
End Else
ErrorMsg = "RESTORE"
Gosub MsgAlert
If rv = Yes$ Then
AuditId = rVal
OrigId = Get_Property(Win$:".EDL_ID", "INVALUE")
Begin Case
Case AuditId = ""
ErrorMsg = "ID"
IdName = "Audit Primary Key"
Gosub MsgAlert
Case OrigId = ""
ErorMsg = "ID"
IdName = "Primary Key"
Gosub MsgAlert
Case Otherwise$
Open TableName To hORT Then
Open "AUDIT_":TableName To hADT Then
ReadO Record From hADT, AuditId Then
Write Record To hORT, OrigId Then
ErrorMsg = "RESTORED"
Gosub MsgAlert
End Else
RecId = OrigId
ErrorMsg = "WRITE"
Gosub MsgAlert
End
End Else
ErrorMsg = "READ"
RecId = AuditId
Gosub MsgAlert
End
End Else
ErrorMsg = "OPEN"
Gosub MsgAlert
End
End Else
ErrorMsg = "OPEN"
Gosub MsgAlert
End
End Case
End
End
return
CLICK.PUB_RETURN:
*----------------------------------------------------------------------------------------------------
*
*----------------------------------------------------------------------------------------------------
Send_Event(@Window, "PAGE", 1)
cWin$ = @Window
Page = 1
Gosub ResetTabOrder
return
CLICK.PUB_COMPARE:
*----------------------------------------------------------------------------------------------------
*
*----------------------------------------------------------------------------------------------------
Post_Event(@Window, "PAGE", 2)
OrigWin$ = Get_Property(@Window:".EDL_WINDOW", "INVALUE")
TableName = Get_Property(OrigWin$:".COB_TABLE", "INVALUE")
Convert @Lower_Case to @Upper_Case In TableName
RecId = Get_Property(OrigWin$:".EDL_ID", "INVALUE")
Open TableName to hORT Then
ReadO RecInfo From hORT, RecId Then
Open "AUDIT_":TableName to hART Then
ARecId = Get_Property(@Window:".EDL_AREC_ID", "INVALUE")
ReadO ARecInfo From hART, ARecId Then
cWin$ = @Window
Page = 2
Gosub ResetTabOrder
Gosub CompareValues
End
End
End
End
return
MENU.EXPAND_ROW:
FocusCtrl = Get_Property("SYSTEM", "FOCUS")
* Set_Property(FocusCtrl, "OLE.ReadOnly", No$)
Send_Message(FocusCtrl, "OLE.ExpandCurrLine")
* Set_Property(FocusCtrl, "OLE.ReadOnly", Yes$)
return
MENU.COLLAPSE_ROW:
FocusCtrl = Get_Property("SYSTEM", "FOCUS")
* Set_Property(FocusCtrl, "OLE.ReadOnly", No$)
Send_Message(FocusCtrl, "OLE.CollapseCurrLine")
* Set_Property(FocusCtrl, "OLE.ReadOnly", Yes$)
return
MENU.NEXT_DIFFERENCE:
FocusCtrl = Get_Property("SYSTEM", "FOCUS")
Send_Message(FocusCtrl, "OLE.GotoMarker")
Begin Case
Case FocusCtrl EQ @Window:".OLE_ARCHIVE"
Set_Property(@Window:".OLE_ORIGINAL", "OLE.TopLine", Get_Property(@Window:".OLE_ARCHIVE", "OLE.TopLine"))
Case FocusCtrl EQ @Window:".OLE_ORIGINAL"
Set_Property(@Window:".OLE_ARCHIVE", "OLE.TopLine", Get_Property(@Window:".OLE_ORIGINAL", "OLE.TopLine"))
End Case
return
PosChanged:
TrailWindow = Get_Property(@Window:".EDL_WINDOW", "TEXT")
Table = Get_Property(TrailWindow:".COB_TABLE", "TEXT")
FieldsRec = Get_Property(@Window, "@RECORD_FIELDS")
CurrLine = Get_Property(CtrlEntId, "OLE.CurrPos")<2>
Line = Send_Message(CtrlEntId, "OLE.GetLineField", CurrLine)
Field = ""
If FieldsRec EQ "" then
DictTable = If Table[1, 5] EQ "DICT." then "DICT.SYSCOLUMNS" else "DICT.":Table
Open DictTable to hTable then
Read FieldsRec from hTable, "%FIELDS%" then
Set_Property(@Window, "@RECORD_FIELDS", FieldsRec)
end
end
end
Fields = FieldsRec<3>
Positions = FieldsRec<5>
Locate Line in Positions setting Pos then
Field = Fields<1, Pos>
end
Set_Property(@Window:".STA_COLUMN", "TEXT", Field)
return
OnVScroll.OLE_ARCHIVE:
Set_Property(@Window:".OLE_ORIGINAL", "OLE.TopLine", Param1)
return
OnVScroll.OLE_ORIGINAL:
Set_Property(@Window:".OLE_ARCHIVE", "OLE.TopLine", Param1)
return
*------------------------
* Internal Processes
*------------------------
CompareValues:
*----------------------------------------------------------------------------------------------------
*
*----------------------------------------------------------------------------------------------------
dRow = ""
MxORows = Count(RecInfo, @FM) + (RecInfo NE "")
MxARows = Count(ARecINfo, @FM) + (ARecInfo NE "")
If MxORows GE MxARows Then
MxRows = MxORows
End Else
MxRows = MxARows
End
For X = 1 to MxRows
If RecInfo<X> NE ARecInfo<X> Then
dRow<-1> = X
End
Next X
If dRow NE "" Then
Ctrls = @Window:".OLE_ARCHIVE":@RM:@Window:".OLE_ORIGINAL":@RM:@Window:".OLE_VIEWER"
* Props = "OLE.ErrorLines":@RM:"OLE.ErrorLines":@RM:"OLE.ErrorLines"
Props = "OLE.MismatchLines":@RM:"OLE.MismatchLines":@RM:"OLE.MismatchLines"
Vals = dRow:@RM:dRow:@RM:dRow
Set_Property(Ctrls, Props, Vals)
End
return
MsgAlert:
*-------------------------------------------------------------------------------------------------------------------------------------
*
*-------------------------------------------------------------------------------------------------------------------------------------
Mess = ""
Mess<MTYPE$> = "BO"
Mess<MICON$> = "!"
Mess<MCAPTION$> = "Audit Trail"
Error = "An undefined error has occurred with this process"
Begin Case
Case ErrorMsg = "OPEN"
Error = "Unable to Open the ": TableName: " table."
Case ErrorMsg = "READ"
Error = "Unable to Read ": RecId:" record."
Case ErrorMsg = "WRITE"
Error = "Unable to Write ": RecId:" record."
Case ErrorMsg = "NOIDS"
Error = "There are no audit records for the ":TableName:" table."
Case ErrorMsg = "ID"
Error = IdName: " is Null."
Case ErrorMsg = "RESTORED"
Error = "Record ":OrigId:" has been restored to the ":TableName:" table."
Case ErrorMsg = "TOOMANY"
Error = "You only restore one record at a time."
Case ErrorMsg = "RESTORE"
Mess<MICON$> = "?"
Mess<MTYPE$> = "BNY"
Error = "Would you like to restore this entry?"
Case ErrorMsg = "NOTABLE"
Error = "No Table Selected"
End Case
Mess<MTEXT$> = Error
rv = Msg("",Mess)
return
ResetTabOrder:
*-------------------------------------------------------------------------------------------------------------------------
* Resets Tab Order
*-------------------------------------------------------------------------------------------------------------------------
LastPageCtrl = ""
LastCtrl = ""
FirstCtrl = ""
rVal = ""
PCtrls = ""
NCtrls = ""
NProps = ""
Begin Case
Case cWin$ EQ "NDW_AUDIT_TRAIL"
rVal<1> = @Window:".COB_TABLE"
rVal<2> = @Window:".EDL_ID"
rVal<3> = @Window:".EDT_AUDIT_INFO"
rVal<4> = @Window:".PUB_RESTORE"
rVal<5> = @Window:".PUB_VIEW"
Case Otherwise$
Begin Case
Case Page EQ 1
Set_Property("SYSTEM", "FOCUS", cWin$:".OLE_VIEWER")
rVal<1> = cWin$:".OLE_VIEWER"
rVal<2> = cWin$:".PUB_RESTORE"
rVal<3> = cWin$:".PUB_COMPARE"
rVal<4> = cWin$:".PUB_CLOSE"
Case Page EQ 2
Set_Property("SYSTEM", "FOCUS", cWin$:".OLE_ARCHIVE")
rVal<1> = cWin$:".OLE_ARCHIVE"
rVal<2> = cWin$:".OLE_ORIGINAL"
rVal<3> = cWin$:".PUB_RESTORE"
rVal<4> = cWin$:".PUB_RETURN"
rVal<5> = cWin$:".PUB_CLOSE"
End Case
End Case
MxC = Count(rVal,@FM) + (rVal NE "")
For i = 1 to MxC
If i = MxC Then
nVal = 1
End Else
nVal = i + 1
End
PCtrls<-1> = rVal<i>
NCtrls<-1> = rVal<nVal>
NProps<-1> = "NEXT"
Next i
Convert @FM to @RM in PCtrls
Convert @FM to @RM in NCtrls
Convert @FM to @RM in NProps
Set_Property(PCtrls, NProps, NCtrls)
return

View File

@ -0,0 +1,290 @@
Function NDW_HTTP_DatePicker_Events(CtrlEntId, Event, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : NDW_HTTP_DatePicker_Events
Description : This function acts as a commuter module for all events related to this window.
Notes : Commuter Modules are automatically called from the Promoted_Events function which is called by the
application-specific promoted event handler. This makes it possible to add QuickEvents that need to
execute Basic+ logic without having use the Form Designer to make the association, although this is
limited to the events which are currently promoted.
If the form needs to call the commuter module directly then the QuickEvent parameters should be
formatted like this:
'@SELF','@EVENT',['@PARAM1','@PARAMx']
Parameters :
CtrlEntId [in] -- The fully qualified name of the control calling the promoted event
Event [in] -- The event being executed. See the Notes section regarding "PRE" events
Param1-15 [in] -- Additional event parameter holders
EventFlow [out] -- Set to 1 or 0 so the calling event knows whether or not to chain forward. See comments in
EVENT_SETUP insert
History (Date, Initials, Notes)
07/18/19 dmb Original programmer although ported the NDW_DATEPICKER from FrameWorks as a base.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
#window NDW_HTTP_DATEPICKER
$insert LOGICAL
$insert MSG_EQUATES
Equ EVENT_CONTINUE$ to 1
Equ EVENT_CONTINUE_NO_SYSTEM$ to 3
Equ EVENT_STOP$ to 0
Equ CRLF$ to \0D0A\
Declare subroutine Set_Property, Send_Event, Post_Event, Send_Message, SendMessage, End_Dialog
Declare function Get_Property, SRP_Get_Window_Rect, Send_Message, SendMessage
// Get the design time name of the window in case this is a multi-instance window.
Window = @Window[1, 'F*']
// Always get the CtrlClassID since we are not passing it through the event parameters.
CtrlClassId = Get_Property(CtrlEntId, 'TYPE')
// Get the name of the control on the window based on the CtrlClassId.
Begin Case
Case CtrlClassId EQ 'WINDOW'
Control = Window
Case CtrlClassId EQ 'RADIOBUTTON'
Control = Field(CtrlEntId, '.', 2, 2)
Case CtrlClassId EQ 'MENU'
Control = CtrlEntId[-1, 'B.']
Case 1
Control = Field(CtrlEntId, '.', 2, 1)
End Case
If Event EQ 'OLE' then GoSub TransferParams
GoToEvent Event for CtrlEntID
If Event EQ 'OLE' then GoSub RestoreParams
Return EventFlow OR EVENT_CONTINUE$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Events
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Event WINDOW.CREATE(CreateParam)
GoSub SetupOLEControls
GoSub DeterminePosition
Set_Property(@Window, 'SIZE', Size)
end event
Event WINDOW.INACTIVATED()
Post_Event(@Window, 'CLOSE')
end event
Event PUB_OK.CLICK()
GoSub ReturnDate
return
Event OLE_DATEPICKER.OnDblClick(Month, Week, DayOfWeek, Date, Point, Button, Shift, Ctrl)
If Date NE '' then
GoSub ReturnDate
end
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal Gosubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SetupOLEControls:
// All OLE controls can use this qualify configuration.
Qualify = ''
Qualify<1> = 1
Qualify<3> = ''
Qualify<4> = 0
//------------------------------------------------------------------------------------------------------------------
//
// SRP DatePicker Control
//
//------------------------------------------------------------------------------------------------------------------
Ctrl = @Window : '.OLE_DATEPICKER'
SizeWindow = Get_Property(@Window, 'SIZE')
SizePicker = -1 : @FM : -1 : @FM : SizeWindow<3> : @FM : SizeWindow<4>
Set_Property(Ctrl, 'SIZE', SizePicker)
Set_Property(Ctrl, 'OLE.Theme', 'Windows7Blue')
Set_Property(Ctrl, 'OLE.Font', 'Segoe UI' : @SVM : 9 : @SVM : 400)
// Use asynchronous event handling (because in Dialog Box)
Send_Message(@Window : '.OLE_DATEPICKER', 'QUALIFY_EVENT', 'OLE.OnDblClick', Qualify)
return
TransferParams:
// ActiveX controls pass their own event names through Param1. Modify the parameter values so they conform to
// OpenInsight event parameter values. This will allow commuter modules to be structured the same for OpenInsight
// event and ActiveX (OLE) events.
Transfer Param1 to Event
Transfer Param2 to Param1
Transfer Param3 to Param2
Transfer Param4 to Param3
Transfer Param5 to Param4
Transfer Param6 to Param5
Transfer Param7 to Param6
Transfer Param8 to Param7
Transfer Param9 to Param8
Transfer Param10 to Param9
Transfer Param11 to Param10
Transfer Param12 to Param11
Transfer Param13 to Param12
Transfer Param14 to Param13
Transfer Param15 to Param14
return
RestoreParams:
// Restore the event parameters so the rest of the event chain will see the parameter values as they were originally
// created by OpenInsight. This will also prevent the parameter values from being transferred multiple times in case
// there are multiple OLE promoted event handlers (e.g. APPNAME*..OIWIN* and APPNAME*OLE..OIWIN*).
Transfer Param14 to Param15
Transfer Param13 to Param14
Transfer Param12 to Param13
Transfer Param11 to Param12
Transfer Param10 to Param11
Transfer Param9 to Param10
Transfer Param8 to Param9
Transfer Param7 to Param8
Transfer Param6 to Param7
Transfer Param5 to Param6
Transfer Param4 to Param5
Transfer Param3 to Param4
Transfer Param2 to Param3
Transfer Param1 to Param2
Transfer Event to Param1
Event = 'OLE'
return
DeterminePosition:
Parent = Get_Property(@Window, 'PARENT')
// Determine the control to do the lookup for
CtrlId = Get_Property(Parent, 'FOCUS')
// Get some property values
Ctrls = Parent : @RM : @Window : @RM : CtrlId : @RM : CtrlId : @RM : CtrlId : @RM : CtrlId : @RM : 'SYSTEM'
Props = 'MDIFRAME' : @RM : 'SIZE' : @RM : 'TYPE' : @RM : 'HANDLE' : @RM : 'SELPOS' : @RM : 'ORIG_TEXT' : @RM : 'SIZE'
Vals = Get_Property(Ctrls, Props)
Frame = Field(Vals, @RM, 1)
Size = Field(Vals, @RM, 2)
Type = Field(Vals, @RM, 3)
CtlHdl = Field(Vals, @RM, 4)
SelPos = Field(Vals, @RM, 5)
ProgID = Field(Vals, @RM, 6) ; // To check for OLE EditTables
Screen = Field(Vals, @RM, 7)
// If no frame, use window size to determine if calendar should show below or above control
If Frame then
WinSize = SRP_Get_Window_Rect(Frame)
end else
WinSize = SRP_Get_Window_Rect(Parent)
end
Table = (Type EQ 'EDITTABLE') OR (ProgID _EQC 'SRP.EditTable.1')
If Table else
SelPos = ''
end
If ProgID _EQC 'SRP.EditTable.1' then
// OLE EditTables need to use the CellText property
ColNo = SelPos<1>
RowNo = SelPos<2>
Convert @FM to ';' in SelPos
DfltDate = Iconv(Get_Property(CtrlId, 'OLE.CellText[':SelPos:']'), 'D')
end else
DfltDate = Get_Property(CtrlId, 'INVALUE', SelPos)
end
// Set initial selection to date passed in and make it visible
If DfltDate then
Set_Property(@Window:'.OLE_DATEPICKER', 'OLE.Selection', DfltDate)
Send_Message(@Window:'.OLE_DATEPICKER', 'OLE.EnsureVisible', DfltDate)
end
Rect = Str(\00\, 16)
CtlSize = SRP_Get_Window_Rect(CtrlId)
xPos = CtlSize<1>
yPos = CtlSize<2>
If Table then
// add x, y and y+h of cell
If ProgID _EQC 'SRP.EditTable.1' then
CellSize = Send_Message(CtrlId, 'OLE.GetCellRect', ColNo:@FM:RowNo)
*xPos += CellSize<1>
xPos += CellSize<1> + 1 ; // This makes alignment better
yPos += CellSize<2>
cyPos = yPos + CellSize<4>
end else
LeftBottom = SendMessage(CtlHdl, DTM_GETCELLLEFTBOTTOM$, DTA_CURRENT$, 0)
xPos += mod(LeftBottom, 65536)
cyPos = yPos + int(LeftBottom / 65536)
// Get y position with different SendMessage call
SendMessage(CtlHdl, DTM_READCELLRECT$, DTA_CURRENT$, GetPointer(Rect))
yPos += seq(Rect [5,1]) + (seq(Rect [6,1]) * 256)
end
end else
// get y+h of control
cyPos = CtlSize<2> + CtlSize<4>
end
// get y+h of frame or parent window
MaxCy = WinSize<2> + WinSize<4>
// Set x and y of calendar window
Size<1> = xPos
If Size<1> + Size<3> GT Screen<1> AND (Screen<1> GT Size<1>) then
// Shift calendar to left to fit on screen
Size<1> = Screen<1> - Size<3>
end
If cyPos+Size<4> GT MaxCy then
// Position above control so calendar shows fully
Size<2> = yPos - Size<4>
end else
Size<2> = cyPos
end
return
ReturnDate:
SelDate = Get_Property(@Window : '.OLE_DATEPICKER', 'OLE.Selection')
End_Dialog(@Window, SelDate)
// Since we are ending the window now, there is no need to allow the event chain to continue.
// If we do, then we will get the "labeled common variable has been freed and is no longer valid" error.
EventFlow = EVENT_CONTINUE_NO_SYSTEM$
return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
Function NDW_HTTP_Logs_Archive_Date_Events(CtrlEntId, Event, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : NDW_HTTP_Logs_Archive_Date_Events
Description : This function acts as a commuter module for all events related to this window.
Notes : Commuter Modules are automatically called from the Promoted_Events function which is called by the
application-specific promoted event handler. This makes it possible to add QuickEvents that need to
execute Basic+ logic without having use the Form Designer to make the association, although this is
limited to the events which are currently promoted.
If the form needs to call the commuter module directly then the QuickEvent parameters should be
formatted like this:
'@SELF','@EVENT',['@PARAM1','@PARAMx']
Parameters :
CtrlEntId [in] -- The fully qualified name of the control calling the promoted event
Event [in] -- The event being executed. See the Notes section regarding "PRE" events
Param1-15 [in] -- Additional event parameter holders
EventFlow [out] -- Set to 1 or 0 so the calling event knows whether or not to chain forward. See comments in
EVENT_SETUP insert
History (Date, Initials, Notes)
09/23/19 dmb [SRPFW-278] Initial development.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
#window NDW_HTTP_LOGS_ARCHIVE_DATE
$insert LOGICAL
$insert MSG_EQUATES
Equ EVENT_CONTINUE$ to 1
Equ EVENT_STOP$ to 0
Equ CR$ to \0D\
Equ CRLF$ to \0D0A\
Equ BACKSPACE$ to \08\
Equ TAB$ to \09\
Equ NEXT$ to 1
Equ PREVIOUS$ to 2
Declare subroutine Set_Property, Send_Event, Send_Message, PlaceDialog, End_Dialog
Declare function Get_Property, Dialog_Box
// Get the design time name of the window in case this is a multi-instance window.
Window = @Window[1, 'F*']
// Always get the CtrlClassID since we are not passing it through the event parameters.
CtrlClassId = Get_Property(CtrlEntId, 'TYPE')
// Get the name of the control on the window based on the CtrlClassId.
Begin Case
Case CtrlClassId EQ 'WINDOW'
Control = Window
Case CtrlClassId EQ 'RADIOBUTTON'
Control = Field(CtrlEntId, '.', 2, 2)
Case CtrlClassId EQ 'MENU'
Control = CtrlEntId[-1, 'B.']
Case 1
Control = Field(CtrlEntId, '.', 2, 1)
End Case
If Event EQ 'OLE' then GoSub TransferParams
GoToEvent Event for CtrlEntID
If Event EQ 'OLE' then GoSub RestoreParams
Return EventFlow OR EVENT_CONTINUE$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Events
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Event WINDOW.CREATE(CreateParam)
GoSub SetupOLEControls
PlaceDialog(-1, -1)
end event
Event PUB_OK.CLICK()
ArchiveDate = Get_Property(@Window : '.EDL_DATE', 'INVALUE')
End_Dialog(@Window, ArchiveDate)
// Since we are ending the window now, there is no need to allow the event chain to continue.
// If we do, then we will get the "labeled common variable has been freed and is no longer valid" error.
EventFlow = EVENT_STOP$
end event
Event EDL_DATE.OPTIONS()
CurrentDate = Get_Property(@Window : '.EDL_DATE', 'INVALUE')
NewDate = Dialog_Box('NDW_HTTP_DATEPICKER', @Window)
If CurrentDate NE NewDate then
Set_Property(CtrlEntId, 'INVALUE', NewDate)
end
end event
Event OLE_SUBCLASS.OnOptionClick(CtrlId)
Send_Event(CtrlId, 'OPTIONS')
end event
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal Gosubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SetupOLEControls:
// All OLE controls can use this qualify configuration.
Qualify = ''
Qualify<1> = 1
Qualify<3> = ''
Qualify<4> = 0
//------------------------------------------------------------------------------------------------------------------
//
// SRP Subclass Control
//
//------------------------------------------------------------------------------------------------------------------
Ctrl = @Window : '.OLE_SUBCLASS'
EditCtrls = 'EDL_DATE'
NumCtrls = DCount(EditCtrls, ',')
For EditCnt = 1 to NumCtrls
EditCtrl = Field(EditCtrls, ',', EditCnt, 1)
Handle = Get_Property(@Window : '.' : EditCtrl, 'HANDLE')
Send_Message(Ctrl, 'OLE.Subclass', Handle, @Window : '.' : EditCtrl)
Set_Property(Ctrl, 'OLE.OptionButton[' : @Window : ';' : EditCtrl : ']', True$)
Set_Property(Ctrl, 'OLE.OptionImage[' : @Window : ';' : EditCtrl : ']', 'BMPS\SRPHTTPDateField.png')
Set_Property(Ctrl, 'OLE.Prompt[' : @Window : ';' : EditCtrl : ']', 'YYYY-MM-DD' : @FM : @FM : 'Center' : @FM : 'Center' : @FM : 'Segoe UI' : @SVM : 9 : @SVM : 400 : @VM : 0)
Send_Message(Ctrl, 'QUALIFY_EVENT', 'OLE.OnOptionClick', Qualify)
Next EditCnt
return
TransferParams:
// ActiveX controls pass their own event names through Param1. Modify the parameter values so they conform to
// OpenInsight event parameter values. This will allow commuter modules to be structured the same for OpenInsight
// event and ActiveX (OLE) events.
Transfer Param1 to Event
Transfer Param2 to Param1
Transfer Param3 to Param2
Transfer Param4 to Param3
Transfer Param5 to Param4
Transfer Param6 to Param5
Transfer Param7 to Param6
Transfer Param8 to Param7
Transfer Param9 to Param8
Transfer Param10 to Param9
Transfer Param11 to Param10
Transfer Param12 to Param11
Transfer Param13 to Param12
Transfer Param14 to Param13
Transfer Param15 to Param14
return
RestoreParams:
// Restore the event parameters so the rest of the event chain will see the parameter values as they were originally
// created by OpenInsight. This will also prevent the parameter values from being transferred multiple times in case
// there are multiple OLE promoted event handlers (e.g. APPNAME*..OIWIN* and APPNAME*OLE..OIWIN*).
Transfer Param14 to Param15
Transfer Param13 to Param14
Transfer Param12 to Param13
Transfer Param11 to Param12
Transfer Param10 to Param11
Transfer Param9 to Param10
Transfer Param8 to Param9
Transfer Param7 to Param8
Transfer Param6 to Param7
Transfer Param5 to Param6
Transfer Param4 to Param5
Transfer Param3 to Param4
Transfer Param2 to Param3
Transfer Param1 to Param2
Transfer Event to Param1
Event = 'OLE'
return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,403 @@
Function NDW_Web_Accounts_Events(CtrlEntId, Event, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : NDW_Web_Accounts_Events
Description : This function acts as a commuter module for all events related to this window.
Notes : Commuter Modules are automatically called from the Promoted_Events function which is called by the
application-specific promoted event handler. This makes it possible to add QuickEvents that need to
execute Basic+ logic without having use the Form Designer to make the association, although this is
limited to the events which are currently promoted.
If the form needs to call the commuter module directly then the QuickEvent parameters should be
formatted like this:
'@SELF','@EVENT',['@PARAM1','@PARAMx']
Parameters :
CtrlEntId [in] -- The fully qualified name of the control calling the promoted event
Event [in] -- The event being executed. See the Notes section regarding "PRE" events
Param1-15 [in] -- Additional event parameter holders
EventFlow [out] -- Set to 1 or 0 so the calling event knows whether or not to chain forward. See comments in
EVENT_SETUP insert
History (Date, Initials, Notes)
10/24/18 dmb Initial development.
11/21/18 dmb [SRPFW-257] Finish core functionality.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
#window NDW_WEB_ACCOUNTS
$insert LOGICAL
$insert MSG_EQUATES
$insert WEB_ACCOUNTS_EQUATES
Equ EVENT_CONTINUE$ to 1
Equ EVENT_STOP$ to 0
Equ SetupTable$ to 'SYSENV'
Declare subroutine WebAccounts_Services, Set_Property, PlaceDialog, End_Dialog, Msg, Send_Event, Send_Message
Declare subroutine Error_Services, HTTP_Authentication_Services
Declare function WebAccounts_Services, Get_Property, Memory_Services, HTTP_Authentication_Services, Error_Services
Declare function RTI_CreateGUID, Popup
// Get the design time name of the window in case this is a multi-instance window.
Window = @Window[1, 'F*']
// Always get the CtrlClassID since we are not passing it through the event parameters.
CtrlClassId = Get_Property(CtrlEntId, 'TYPE')
// Get the name of the control on the window based on the CtrlClassId.
Begin Case
Case CtrlClassId EQ 'WINDOW'
Control = Window
Case CtrlClassId EQ 'RADIOBUTTON'
Debug
* Control = Field(CtrlEntId, '.', 2, 2)
Control = Field(CtrlEntId, '.', 2, 1)
Case CtrlClassId EQ 'MENU'
Control = CtrlEntId[-1, 'B.']
Case 1
Control = Field(CtrlEntId, '.', 2, 1)
End Case
If Event EQ 'OLE' then GoSub TransferParams
GoToEvent Event for CtrlEntID
If Event EQ 'OLE' then GoSub RestoreParams
Return EventFlow OR EVENT_CONTINUE$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Events
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Event WINDOW.CREATE(CreateParam)
GoSub SetupOLEControls
PlaceDialog(-2, -2)
end event
Event EDL_ID.LOSTFOCUS(Flag, FocusID)
GotFocusID = Get_Property(CtrlEntId, 'GOTFOCUS_VALUE')
ID = Get_Property(CtrlEntId, 'TEXT')
If GotFocusID NE ID then
WebAccountRow = WebAccounts_Services('GetWebAccounts', ID)
If Error_Services('NoError') then
GoSub UpdateForm
end
end
end event
Event EDL_ID.OPTIONS()
ID = Popup(@Window, '', 'WEB_ACCOUNTS')
If ID NE '' AND ID NE Char(27) then
Set_Property(CtrlEntId, 'GOTFOCUS_VALUE', '')
Set_Property(CtrlEntId, 'TEXT', ID)
Send_Event(CtrlEntId, 'LOSTFOCUS')
end
end event
Event OLE_ACTION_BAR.OnClick(Group, Item, Point, Button, Shift, Ctrl)
ResetAttempts = False$
Begin Case
Case Group EQ 1
Begin Case
Case Item EQ 1
// Clear Form
ID = ''
WebAccountRow = ''
GoSub UpdateForm
Set_Property('SYSTEM', 'FOCUS', @Window : '.EDL_ID')
Set_Property(@Window : '.EDL_ID', 'GOTFOCUS_VALUE', '')
Case Item EQ 2
// Close Form
Set_Property(@Window, 'TIMER', 1 : @FM : 1)
End Case
Case Group EQ 2
Begin Case
Case Item EQ 1
// New Account
GoSub CreateNewWebAccount
Case Item EQ 2
// Save Account
GoSub UpdateWebAccount
End Case
Case Group EQ 3
Begin Case
Case Item EQ 1
// Reset Password
ID = Get_Property(@Window : '.EDL_ID', 'TEXT')
If ID NE '' then
CurrentPassword = HTTP_Authentication_Services('GetWebAccountPassword', ID, False$)
Password = HTTP_Authentication_Services('ResetWebAccountPassword', ID, CurrentPassword)
If Error_Services('NoError') then
WebAccountRow = WebAccounts_Services('GetWebAccounts', ID)
If Error_Services('NoError') then
GoSub UpdateForm
end
end else
MsgStruct = ''
MsgStruct<MTEXT$> = Error_Services('GetMessage')
MsgStruct<MTYPE$> = 'BO'
MsgStruct<MICON$> = 'H'
MsgStruct<MCAPTION$> = 'SRP HTTP Framework'
Msg(@Window, MsgStruct)
end
end
Case Item EQ 2
// Reset Attempts
ResetAttempts = True$
GoSub UpdateWebAccount
If Error_Services('NoError') then
Set_Property(@Window : '.EDL_INVALID_PASSWORD_ATTEMPTS', 'INVALUE', 0)
end
Case Item EQ 3
// Copy to Clipboard
AccountID = Get_Property(@Window : '.EDL_ID', 'INVALUE')
Name = Get_Property(@Window : '.EDL_NAME', 'INVALUE')
Password = Get_Property(@Window : '.EDL_CURRENT_PASSWORD', 'INVALUE')
Clipboard = 'Account ID: ' : AccountID : \0D0A\ : 'Name: ' : Name : \0D0A\ : 'Password: ' : Password
Set_Property('CLIPBOARD', 'TEXT', Clipboard)
End Case
End Case
end event
Event OLE_SUBCLASS.OnOptionClick(CtrlId)
Send_Event(CtrlId, 'OPTIONS')
end event
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal Gosubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SetupOLEControls:
// All OLE controls can use this qualify configuration.
Qualify = ''
Qualify<1> = 1
Qualify<3> = ''
Qualify<4> = 0
//------------------------------------------------------------------------------------------------------------------
//
// SRP ShortcutBar Control
//
//------------------------------------------------------------------------------------------------------------------
Ctrl = @Window : '.OLE_ACTION_BAR'
Set_Property(Ctrl, 'OLE.Border', 'XP Flat')
Set_Property(Ctrl, 'OLE.Animation', 'Never')
Set_Property(Ctrl, 'OLE.Theme', 'Office2007Blue')
Set_Property(Ctrl, 'OLE.GroupFont', 'Segoe UI' : @SVM : 11 : @SVM : 400)
Set_Property(Ctrl, 'OLE.ItemFont', 'Segoe UI' : @SVM : 9 : @SVM : 400)
Set_Property(Ctrl, 'OLE.GroupCount', 3)
Set_Property(Ctrl, 'OLE.GroupCaption[1]', 'Form Actions')
Set_Property(Ctrl, 'OLE.GroupCaption[2]', 'Account Actions')
Set_Property(Ctrl, 'OLE.GroupCaption[3]', 'Password Actions')
Set_Property(Ctrl, 'OLE.GroupExpandable[All]', False$)
Set_Property(Ctrl, 'OLE.GroupSpecial[All]', True$)
Set_Property(Ctrl, 'OLE.GroupItemCount[1]', 2)
Set_Property(Ctrl, 'OLE.ItemCaption[1;1]', 'Clear Form')
Set_Property(Ctrl, 'OLE.ItemCaption[1;2]', 'Close Form')
Set_Property(Ctrl, 'OLE.GroupItemCount[2]', 2)
Set_Property(Ctrl, 'OLE.ItemCaption[2;1]', 'New Account')
Set_Property(Ctrl, 'OLE.ItemCaption[2;2]', 'Save Account')
Set_Property(Ctrl, 'OLE.GroupItemCount[3]', 3)
Set_Property(Ctrl, 'OLE.ItemCaption[3;1]', 'Reset Password')
Set_Property(Ctrl, 'OLE.ItemCaption[3;2]', 'Reset Attempts')
Set_Property(Ctrl, 'OLE.ItemCaption[3;3]', 'Copy to Clipboard')
Margins = 0 : @FM : 0 : @FM : 0 : @FM : 0 : @FM : 0
Set_Property(Ctrl, 'OLE.HotTrackStyle', 'Item')
Set_Property(Ctrl, 'OLE.ItemBold[All; All]', True$)
Send_Message(Ctrl, 'QUALIFY_EVENT', 'OLE.OnClick', Qualify)
//------------------------------------------------------------------------------------------------------------------
//
// SRP Subclass Control
//
//------------------------------------------------------------------------------------------------------------------
Ctrl = @Window : '.OLE_SUBCLASS'
EditCtrls = 'EDL_ID'
NumCtrls = DCount(EditCtrls, ',')
For EditCnt = 1 to NumCtrls
EditCtrl = Field(EditCtrls, ',', EditCnt, 1)
Handle = Get_Property(@Window : '.' : EditCtrl, 'HANDLE')
Send_Message(Ctrl, 'OLE.Subclass', Handle, @Window : '.' : EditCtrl)
Set_Property(Ctrl, 'OLE.OptionButton[' : @Window : ';' : EditCtrl : ']', True$)
Send_Message(Ctrl, 'QUALIFY_EVENT', 'OLE.OnOptionClick', Qualify)
Next EditCnt
return
TransferParams:
// ActiveX controls pass their own event names through Param1. Modify the parameter values so they conform to
// OpenInsight event parameter values. This will allow commuter modules to be structured the same for OpenInsight
// event and ActiveX (OLE) events.
Transfer Param1 to Event
Transfer Param2 to Param1
Transfer Param3 to Param2
Transfer Param4 to Param3
Transfer Param5 to Param4
Transfer Param6 to Param5
Transfer Param7 to Param6
Transfer Param8 to Param7
Transfer Param9 to Param8
Transfer Param10 to Param9
Transfer Param11 to Param10
Transfer Param12 to Param11
Transfer Param13 to Param12
Transfer Param14 to Param13
Transfer Param15 to Param14
return
RestoreParams:
// Restore the event parameters so the rest of the event chain will see the parameter values as they were originally
// created by OpenInsight. This will also prevent the parameter values from being transferred multiple times in case
// there are multiple OLE promoted event handlers (e.g. APPNAME*..OIWIN* and APPNAME*OLE..OIWIN*).
Transfer Param14 to Param15
Transfer Param13 to Param14
Transfer Param12 to Param13
Transfer Param11 to Param12
Transfer Param10 to Param11
Transfer Param9 to Param10
Transfer Param8 to Param9
Transfer Param7 to Param8
Transfer Param6 to Param7
Transfer Param5 to Param6
Transfer Param4 to Param5
Transfer Param3 to Param4
Transfer Param2 to Param3
Transfer Param1 to Param2
Transfer Event to Param1
Event = 'OLE'
return
UpdateForm:
Set_Property(@Window : '.EDL_ID', 'INVALUE', ID)
Set_Property(@Window : '.EDL_NAME', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.NAME$>)
Set_Property(@Window : '.COB_ACCOUNT_ENABLED', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.ACCOUNT_ENABLED$>)
Set_Property(@Window : '.EDL_CURRENT_PASSWORD', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD$>)
Set_Property(@Window : '.EDL_CURRENT_PASSWORD_CREATE_DATE', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_DATE$>)
Set_Property(@Window : '.EDL_CURRENT_PASSWORD_CREATE_TIME', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_TIME$>)
Set_Property(@Window : '.EDL_CURRENT_PASSWORD_EXPIRE_DATE', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_DATE$>)
Set_Property(@Window : '.EDL_CURRENT_PASSWORD_EXPIRE_TIME', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_TIME$>)
Set_Property(@Window : '.EDL_OLD_PASSWORD', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD$>)
Set_Property(@Window : '.EDL_OLD_PASSWORD_CREATE_DATE', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_CREATE_DATE$>)
Set_Property(@Window : '.EDL_OLD_PASSWORD_CREATE_TIME', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_CREATE_TIME$>)
Set_Property(@Window : '.EDL_OLD_PASSWORD_EXPIRE_DATE', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_EXPIRE_DATE$>)
Set_Property(@Window : '.EDL_OLD_PASSWORD_EXPIRE_TIME', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_EXPIRE_TIME$>)
Set_Property(@Window : '.EDL_INVALID_PASSWORD_ATTEMPTS', 'INVALUE', WebAccountRow<WEB_ACCOUNTS.INVALID_PASSWORD_ATTEMPTS$>)
return
CreateNewWebAccount:
Send_Event(@Window : '.OLE_ACTION_BAR', 'OLE', 'OnClick', 1, 1)
ID = RTI_CreateGUID('B')
Convert '.,' to '' in ID
ID = ID[1, 6]
WebAccountRow = ''
WebAccountRow<WEB_ACCOUNTS.ACCOUNT_ENABLED$> = True$
WebAccountRow<WEB_ACCOUNTS.INVALID_PASSWORD_ATTEMPTS$> = 0
WebAccounts_Services('SetWebAccounts', ID, WebAccountRow)
If Error_Services('NoError') then
HTTP_Authentication_Services('ResetWebAccountPassword', ID)
If Error_Services('NoError') then
Set_Property(@Window : '.EDL_ID', 'INVALUE', ID)
WebAccountRow = WebAccounts_Services('GetWebAccounts', ID)
If Error_Services('NoError') then
GoSub UpdateForm
Set_Property(@Window : '.EDL_NAME', 'FOCUS', True$)
end else
MsgStruct = ''
MsgStruct<MTEXT$> = Error_Services('GetMessage')
MsgStruct<MTYPE$> = 'BO'
MsgStruct<MICON$> = 'H'
MsgStruct<MCAPTION$> = 'SRP HTTP Framework'
Msg(@Window, MsgStruct)
end
end else
MsgStruct = ''
MsgStruct<MTEXT$> = Error_Services('GetMessage')
MsgStruct<MTYPE$> = 'BO'
MsgStruct<MICON$> = 'H'
MsgStruct<MCAPTION$> = 'SRP HTTP Framework'
Msg(@Window, MsgStruct)
end
end else
MsgStruct = ''
MsgStruct<MTEXT$> = Error_Services('GetMessage')
MsgStruct<MTYPE$> = 'BO'
MsgStruct<MICON$> = 'H'
MsgStruct<MCAPTION$> = 'SRP HTTP Framework'
Msg(@Window, MsgStruct)
end
return
UpdateWebAccount:
ID = Get_Property(@Window : '.EDL_ID', 'INVALUE')
WebAccountRow = ''
WebAccountRow<WEB_ACCOUNTS.NAME$> = Get_Property(@Window : '.EDL_NAME', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.ACCOUNT_ENABLED$> = Get_Property(@Window : '.COB_ACCOUNT_ENABLED', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD$> = Get_Property(@Window : '.EDL_CURRENT_PASSWORD', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_DATE$> = Get_Property(@Window : '.EDL_CURRENT_PASSWORD_CREATE_DATE', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_TIME$> = Get_Property(@Window : '.EDL_CURRENT_PASSWORD_CREATE_TIME', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_DATE$> = Get_Property(@Window : '.EDL_CURRENT_PASSWORD_EXPIRE_DATE', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_TIME$> = Get_Property(@Window : '.EDL_CURRENT_PASSWORD_EXPIRE_TIME', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD$> = Get_Property(@Window : '.EDL_OLD_PASSWORD', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_CREATE_DATE$> = Get_Property(@Window : '.EDL_OLD_PASSWORD_CREATE_DATE', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_CREATE_TIME$> = Get_Property(@Window : '.EDL_OLD_PASSWORD_CREATE_TIME', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_EXPIRE_DATE$> = Get_Property(@Window : '.EDL_OLD_PASSWORD_EXPIRE_DATE', 'INVALUE')
WebAccountRow<WEB_ACCOUNTS.OLD_PASSWORD_EXPIRE_TIME$> = Get_Property(@Window : '.EDL_OLD_PASSWORD_EXPIRE_TIME', 'INVALUE')
If ResetAttempts EQ True$ then
Attempts = 0
end else
Attempts = Get_Property(@Window : '.EDL_INVALID_PASSWORD_ATTEMPTS', 'INVALUE')
end
WebAccountRow<WEB_ACCOUNTS.INVALID_PASSWORD_ATTEMPTS$> = Attempts
WebAccounts_Services('SetWebAccounts', ID, WebAccountRow)
If Error_Services('HasError') then
MsgStruct = ''
MsgStruct<MTEXT$> = Error_Services('GetMessage')
MsgStruct<MTYPE$> = 'BO'
MsgStruct<MICON$> = 'H'
MsgStruct<MCAPTION$> = 'SRP HTTP Framework'
Msg(@Window, MsgStruct)
end
return

View File

@ -0,0 +1,56 @@
Function Oath_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Oath_API
Description : API logic for the Oath resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client, including query params.
FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.
ParentURL - The URL path preceeding the current endpoint.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [Resource].[HTTPMethod]. For example:
- Oath.POST
- Oath.ID.PUT
- Oath.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
11/22/18 dmb Original programmer. - [SRPFW-256]
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Web APIs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API oath.GET
end api

View File

@ -0,0 +1,61 @@
Function Oauth_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Oauth_API
Description : API logic for the Oauth resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client, including query params.
FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.
EndpointSegment - The URL endpoint segment.
ParentURL - The URL path preceeding the current endpoint.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
- APIPattern must follow this structure Oauth[.ID.[<Property>]]
- HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
Examples:
- Oauth.POST
- Oauth.ID.PUT
- Oauth.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
07/12/19 dmb Original programmer.
01/23/20 dmb [SRPFW-296] Add matching HEAD APIs for all GET APIs.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API oauth.HEAD
API oauth.GET
end api

View File

@ -0,0 +1,167 @@
Function Picture_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Picture_API
Description : API logic for the Picture resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client, including query params.
FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.
ParentURL - The URL path preceeding the current endpoint.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
- APIPattern must follow this structure <Resource>[.ID.[<Property>]]
- HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
Examples:
- Picture.POST
- Picture.ID.PUT
- Picture.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
11/19/18 dmb Original programmer.
01/23/20 dmb [SRPFW-296] Add matching HEAD APIs for all GET APIs.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
$insert CONTACTS_EQUATES
PictureFolder = '\WebAppData\ContactPictures\'
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API picture.GET
API picture.HEAD
// Get the picture's physical file path from the CONTACT database row.
KeyID = ParentSegment
PicturePath = Drive() : HTTP_Resource_Services('GetColumnValues', 'CONTACTS', 'picture', KeyID)
If PicturePath NE '' then
// Verify the picture actually exists.
If Dir(PicturePath) NE '' then
// Get the image extension.
ImageExt = PicturePath[-1, 'B.']
If ImageExt _EQC 'jpg' then ImageExt = 'jpeg'
// Get the best content type that matches the client's and server's ability.
ContentType = HTTP_Services('GetBestContentNegotiation', 'Accept', 'text/plain' : @FM : 'image/' : ImageExt)
If ContentType NE '' then
OSRead PictureBinary from PicturePath then
Begin Case
Case ContentType _EQC 'text/plain'
PictureBody = SRP_Encode(PictureBinary, 'BASE64')
PictureBody = 'data:' : 'image/' : ImageExt : ';base64,' : PictureBody
HTTP_Services('SetResponseHeaderField', 'Content-Encoding', 'base64')
HTTP_Services('SetResponseBody', PictureBody, False$, 'text/plain')
Case ContentType[1, 6] _EQC 'image/'
HTTP_Services('SetResponseBody', PictureBinary, True$, ContentType)
End Case
end else
HTTP_Services('SetResponseError', '', '', 404, 'Picture for contact ' : KeyID : ' does not exist.', FullEndpointURL)
end
end
end else
HTTP_Services('SetResponseError', '', '', 404, 'Picture for contact ' : KeyID : ' does not exist.', FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 404, 'Picture for contact ' : KeyID : ' does not exist.', FullEndpointURL)
end
end api
API picture.PUT
KeyID = ParentSegment
TableName = 'CONTACTS'
ContentType = HTTP_Services('GetHTTPContentType')
If ContentType EQ '' OR ContentType _EQC 'text/plain' then
Open TableName to hTable then
Lock hTable, KeyID then
ResponseStatus = 200 ; // Updating an existing resource.
Read DataRow from hTable, KeyID else
DataRow = ''
ResponseStatus = 201 ; // Creating a new resource.
end
// A URI scheme of the Base64 encoded image will be in the Data variable.
HTTPPostString = HTTP_Services('GetHTTPPostString')
HTTPPostString = HTTP_Services('DecodePercentString', HTTPPostString)
Scheme = HTTPPostString[1, 'F:']
If Scheme _EQC 'data' then
MediaType = HTTPPostString[Col2() + 1, 'F;'] ; // Should be "image/png" or "image/jpg"
Encoding = HTTPPostString[Col2() + 1, 'F,'] ; // Should be "base64"
EncodedData = HTTPPostString[Col2() + 1, Len(HTTPPostString)] ; // Should be the actual Base64 encoded content.
DecodedData = SRP_Decode(EncodedData, 'BASE64')
FileType = MediaType[-1, 'B/']
FileName = KeyID : '.' : FileType
FilePath = Drive() : PictureFolder : FileName
Status() = 0
OSWrite DecodedData to FilePath
StatusCode = Status()
If StatusCode then
Begin Case
Case StatusCode EQ 1 ; Error = 'Bad OS filename. Code: ' : StatusCode
Case StatusCode EQ 2 ; Error = 'Access denied by operating system. Code: ' : StatusCode
Case StatusCode EQ 3 ; Error = 'Disk or directory full. Code: ' : StatusCode
Case StatusCode EQ 4 ; Error = 'File does not exist. Code: ' : StatusCode
Case StatusCode EQ 5 ; Error = 'Unknown error. Code: ' : StatusCode
Case StatusCode EQ 6 ; Error = 'Attempt to write to read-only file. Code: ' : StatusCode
Case Otherwise$ ; Error = 'Unknown error. Code: ' : StatusCode
End Case
HTTP_Services('SetResponseError', '', '', 501, Error, FullEndpointURL)
end else
DataRow<CONTACTS_PICTURE$> = PictureFolder : FileName
Write DataRow to hTable, KeyID then
HTTP_Services('SetResponseStatus', ResponseStatus)
HTTP_Services('SetResponseHeaderField', 'Content-Location', FullEndpointURL)
end else
HTTP_Services('SetResponseError', '', '', 500, 'Error writing ' : KeyID : ' to the ' : TableName : ' table.', FullEndpointURL)
end
end
end else
HTTP_Services('SetResponseError', '', '', 415, '', FullEndpointURL)
end
Unlock hTable, KeyID else Null
end else
HTTP_Services('SetResponseError', '', '', 423, KeyID : ' is currently locked.', FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 500, 'Error opening the ' : TableName : ' table.', FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 415, 'Content-Type ' : ContentType : ' is not supported. Must specify "text/plain" or nothing.', FullEndpointURL)
end
end api

View File

@ -0,0 +1,82 @@
Function Ping_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Ping_API
Description : API logic for the Ping resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client, including query params.
FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.
ParentURL - The URL path preceeding the current endpoint.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
- APIPattern must follow this structure Ping[.ID.[<Property>]]
- HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
Examples:
- Ping.POST
- Ping.ID.PUT
- Ping.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
06/24/19 dmb [SRPFW-276] Original programmer.
01/18/20 dmb [SRPFW-296] Update the ping.GET API by replacing Utility_DotNet('TIMEZONE') with
the SRP_DateTime service (SRP Utilities 2.1) to avoid localization problems and potential
502 Bad Gateway errors.
01/23/20 dmb [SRPFW-296] Add matching HEAD APIs for all GET APIs.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
Declare function SRP_DateTime
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API ping.HEAD
API ping.GET
Properties = 'currentDateTime'
Values = SRP_DateTime('Format', SRP_DateTime('Now', True$), "DDD, DD MMM YYYY hh:mm:ss 'GMT'")
objResource = HTTP_Resource_Services('AddProperties', '', Properties, Values)
Rels = 'self' : @FM : 'apiEntryPoint'
URLs = FullEndpointURL : @FM : APIURL
HTTP_Resource_Services('AddLinkRelations', objResource, Rels, URLs)
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end api

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
Function Version_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Version_API
Description : API logic for the Version resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
- APIPattern must follow this structure <Resource>[.ID.[<Property>]]
- HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
Examples:
- Version.POST
- Version.ID.PUT
- Version.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
11/19/18 dmb Original programmer.
05/28/19 dmb [SRPFW-274] Replace all references to AddLinkRelationships with AddLinkRelations.
01/23/20 dmb [SRPFW-296] Add matching HEAD APIs for all GET APIs.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API version.HEAD
API version.GET
Version = HTTP_Services('GetVersion')
If Error_Services('NoError') then
Swap CRLF$ with @FM in Version
Properties = 'version' : @FM : 'date' : @FM : 'time'
Values = Version<1> : @FM : Field(Version<2>, ' ', 1, 1) : @FM : Field(Version<2>, ' ', 2, 1)
objResource = HTTP_Resource_Services('AddProperties', '', Properties, Values)
Rels = 'self' : @FM : 'apiEntryPoint'
URLs = FullEndpointURL : @FM : APIURL
HTTP_Resource_Services('AddLinkRelations', objResource, Rels, URLs)
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end api

View File

@ -0,0 +1,205 @@
Function Webaccounts_API(@API)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Webaccounts_API
Description : API logic for the Webaccounts resource.
Notes : All web APIs should include the API_SETUP insert. This will provide several useful variables:
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
FullEndpointURL - The URL submitted by the client, including query params.
FullEndpointURLNoQuery - The URL submitted by the client, excluding query params.
ParentURL - The URL path preceeding the current endpoint.
the SelfURL.
CurrentAPI - The name of this stored procedure.
Parameters :
API [in] -- Web API to process. Format is [APIPattern].[HTTPMethod]:
- APIPattern must follow this structure <Resource>[.ID.[<Property>]]
- HTTPMethod can be any valid HTTP method, e.g., GET, POST, PUT, DELETE, etc.
Examples:
- Webaccounts.POST
- Webaccounts.ID.PUT
- Webaccounts.ID.firstName.GET
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
services do not rely upon anything being returned in the response. This is what the
various services like SetResponseBody and SetResponseStatus services are for. A response
value is only helpful if the developers want to use it for debug purposes.
History : (Date, Initials, Notes)
11/19/18 dmb Original programmer.
04/09/19 dmb [SRPFW-271] Replace FullEndpointURL with FullEndpointURLNoQuery in the GetObjects service
within the webaccounts.GET API to avoid query params in the embedded object self URLs.
05/28/19 dmb [SRPFW-274] Replace all references to AddLinkRelationships with AddLinkRelations.
01/23/20 dmb [SRPFW-296] Add matching HEAD APIs for all GET APIs.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert API_SETUP
$insert HTTP_INSERTS
Declare function WebAccounts_Services
AuthenticatedAccountID = HTTP_Authentication_Services('GetAuthenticatedAccountID')
GoToAPI else
// The specific resource endpoint doesn't have a API handler yet.
HTTP_Services('SetResponseStatus', 204, 'This is a valid endpoint but a web API handler has not yet been created.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Endpoint Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
API webaccounts.HEAD
API webaccounts.GET
objResource = HTTP_Resource_Services('GetObject')
If Error_Services('NoError') then
objWebAccounts = HTTP_Resource_Services('GetObject', 'WEB_ACCOUNTS', AuthenticatedAccountID, 'NAME', '', '', '', '', FullEndpointURLNoQuery)
If Error_Services('NoError') then
HTTP_Resource_Services('AddEmbeddedResources', objResource, 'webaccounts', objWebAccounts)
// Add _links sub-properties for HAL implementation.
Rels = 'self' : @FM : 'apiEntryPoint'
URLs = FullEndpointURL : @FM : ParentURL
HTTP_Resource_Services('AddLinkRelations', objResource, Rels, URLs)
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end api
API webaccounts.ID.HEAD
API webaccounts.ID.GET
AccountID = EndpointSegment
If AccountID EQ AuthenticatedAccountID then
objResource = HTTP_Resource_Services('GetObject', 'WEB_ACCOUNTS', AccountID, 'NAME')
If Error_Services('NoError') then
objPassword = HTTP_Resource_Services('GetObject', 'WEB_ACCOUNTS', AccountID, 'CURRENT_PASSWORD' : @FM : 'CURRENT_PASSWORD_CREATED' : @FM : 'CURRENT_PASSWORD_EXPIRES', 'value' : @FM : 'created' : @FM : 'expires')
If Error_Services('NoError') then
// Add the password nested property.
HTTP_Resource_Services('AddProperty', objResource, 'password', objPassword, 'ObjectHandle')
end
If Error_Services('NoError') then
// Add _links sub-properties for HAL implementation.
Names = 'self' : @FM : 'password' : @FM : 'apiEntryPoint'
URLs = FullEndpointURL : @FM : FullEndpointURL : '/password' : @FM : APIURL
HTTP_Resource_Services('AddLinkRelations', objResource, Names, URLs)
end
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 401, 'This account is not authorized for this endpoint.', FullEndpointURL)
end
end api
API webaccounts.ID.password.HEAD
API webaccounts.ID.password.GET
AccountID = ParentSegment
If AccountID EQ AuthenticatedAccountID then
objResource = HTTP_Resource_Services('GetObject', 'WEB_ACCOUNTS', AccountID, 'CURRENT_PASSWORD' : @FM : 'CURRENT_PASSWORD_CREATED' : @FM : 'CURRENT_PASSWORD_EXPIRES', 'value' : @FM : 'created' : @FM : 'expires')
If Error_Services('NoError') then
// Add _links sub-properties for HAL implementation.
Names = 'self' : @FM : 'apiEntryPoint'
URLs = FullEndpointURL : @FM : APIURL
HTTP_Resource_Services('AddLinkRelations', objResource, Names, URLs)
end
If Error_Services('NoError') then
HTTP_Resource_Services('AddFormAction', objResource, 'resetPassword', 'PATCH', FullEndpointURL, 'Reset Password', 'value', '' : @VM : True$ : @VM : True$)
end
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 401, 'This account is not authorized for this endpoint.', FullEndpointURL)
end
end api
API webaccounts.ID.password.PATCH
AccountID = ParentSegment
If AccountID EQ AuthenticatedAccountID then
Password = HTTP_Authentication_Services('GetWebAccountPassword', AccountID, False$)
Body = HTTP_Services('GetHTTPPostString')
Body = HTTP_Services('DecodePercentString', Body)
If SRP_JSON(objJSON, 'Parse', Body) EQ '' then
NewPassword = SRP_JSON(objJSON, 'GetValue', 'value')
SRP_JSON(objJSON, 'Release')
HTTP_Authentication_Services('SetWebAccountPassword', AccountID, Password, NewPassword)
If Error_Services('NoError') then
objResource = HTTP_Resource_Services('GetObject', 'WEB_ACCOUNTS', AccountID, 'CURRENT_PASSWORD' : @FM : 'CURRENT_PASSWORD_CREATED' : @FM : 'CURRENT_PASSWORD_EXPIRES', 'value' : @FM : 'created' : @FM : 'expires')
If Error_Services('NoError') then
// Add _links sub-properties for HAL implementation.
Names = 'self' : @FM : 'apiEntryPoint'
URLs = FullEndpointURL : @FM : APIURL
HTTP_Resource_Services('AddLinkRelations', objResource, Names, URLs)
end
If Error_Services('NoError') then
HTTP_Resource_Services('AddFormAction', objResource, 'resetPassword', 'PATCH', FullEndpointURL, 'Reset Password', 'value', '' : @VM : True$ : @VM : True$)
end
If Error_Services('NoError') then
// Serialize the object into a JSON string.
jsonResource = HTTP_Resource_Services('GetSerializedResource', objResource)
// Set the response body with the JSON string and set the Content-Type response header.
HTTP_Services('SetResponseBody', jsonResource, False$, 'application/hal+json')
end else
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 403, Error_Services('GetMessage'), FullEndpointURL)
end
end else
Error_Services('Add', 'Error parsing JSON body within the ' : CurrentAPI : ' module.')
HTTP_Services('SetResponseError', '', '', 500, Error_Services('GetMessage'), FullEndpointURL)
end
end else
HTTP_Services('SetResponseError', '', '', 401, 'This account is not authorized for this endpoint.', FullEndpointURL)
end
end api

View File

@ -0,0 +1,204 @@
Function WebAccounts_Services(@Service, @Params)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : WebAccounts_Services
Description : Handler program for all WebAccounts services.
Notes :
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
10/13/18 dmb [SRPFW-254] Original programmer.
10/13/18 dmb [SRPFW-254] Add GetWebAccounts, SetWebAccounts, and ConvertMVWebAccountsToJSON serives.
10/22/18 dmb [SRPFW-254] Add ConvertJSONWebAccountsToMV service.
01/18/20 dmb [SRPFW-296] Update the ConvertJSONWebAccountsToMV service by replacing
Utility_DotNet('TIMEZONE') with the SRP_DateTime service (SRP Utilities 2.1) to avoid
localization problems and potential 502 Bad Gateway errors.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
$insert WEB_ACCOUNTS_EQUATES
Equ SecondsPerHour$ to 60 * 60 ; // 60 minutes * 60 seconds = 3600
Equ SecondsPerDay$ to 24 * SecondsPerHour$ ; // 24 hours * 60 minutes * 60 seconds = 86400
Declare function WebAccounts_Services, Memory_Services, Database_Services, SRP_JSON, RTI_CreateGUID, SRP_DateTime
Declare subroutine WebAccounts_Services, Memory_Services, Database_Services, SRP_JSON
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// GetWebAccounts
//
// Returns the database row from the WebAccounts table for the indicated Account ID. The default format is MultiValue.
//----------------------------------------------------------------------------------------------------------------------
Service GetWebAccounts(AccountID, ReturnJSON)
WebAccountsRow = ''
If AccountID NE '' then
WebAccountsRow = Database_Services('ReadDataRow', 'WEB_ACCOUNTS', AccountID)
If ReturnJSON EQ True$ then
WebAccountsRow = WebAccounts_Services('ConvertMVWebAccountsToJSON', AccountID, WebAccountsRow)
end
end else
Error_Services('Add', 'AccountID argument was missing in the ' : Service : ' service.')
end
Response = WebAccountsRow
end service
//----------------------------------------------------------------------------------------------------------------------
// SetWebAccounts
//
// Updates the WebAccounts database row for the indicated Account ID.
//----------------------------------------------------------------------------------------------------------------------
Service SetWebAccounts(AccountID, WebAccountsRow)
If (AccountID NE '') AND (WebAccountsRow NE '') then
Database_Services('WriteDataRow', 'WEB_ACCOUNTS', AccountID, WebAccountsRow)
end else
Error_Services('Add', 'AccountID or WebAccountsRow argument was missing in the ' : Service : ' service.')
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ConvertMVWebAccountsToJSON
//
// Converts a MultiValue formatted WebAccounts row into a serialized JSON object and returns the result. If the
// mvWebAccounts argument is empty, the service will attempt to get it from the WebAccounts table. If the itemURL
// argument is not empty, HAL+JSON properties will be added to the JSON object.
//----------------------------------------------------------------------------------------------------------------------
Service ConvertMVWebAccountsToJSON(AccountID, mvWebAccounts, itemURL)
jsonWebAccounts = ''
If AccountID NE '' then
If mvWebAccounts EQ '' then mvWebAccounts = Database_Services('ReadDataRow', 'WEB_ACCOUNTS', AccountID)
If Error_Services('NoError') then
@DICT = Database_Services('GetTableHandle', 'DICT.WEB_ACCOUNTS')
@ID = AccountID
@RECORD = mvWebAccounts
// WebAccounts object.
If SRP_JSON(objJSONWebAccounts, 'New', 'Object') then
SRP_JSON(objJSONWebAccounts, 'SetValue', 'id', @ID, 'String')
SRP_JSON(objJSONWebAccounts, 'SetValue', 'name', {NAME}, 'String')
If SRP_JSON(objPassword, 'New', 'Object') then
SRP_JSON(objPassword, 'SetValue', 'value', {CURRENT_PASSWORD}, 'String')
SRP_JSON(objPassword, 'SetValue', 'created', {CURRENT_PASSWORD_CREATED}, 'String')
SRP_JSON(objPassword, 'SetValue', 'expires', {CURRENT_PASSWORD_EXPIRES}, 'String')
SRP_JSON(objJSONWebAccounts, 'Set', 'password', objPassword)
SRP_JSON(objPassword, 'Release')
end
jsonWebAccounts = SRP_JSON(objJSONWebAccounts, 'Stringify', 'Styled')
* Swap \0D0A\ with @FM in jsonWebAccounts
SRP_JSON(objJSONWebAccounts, 'Release')
end else
Error_Services('Add', 'Unable to create JSON representation in the ' : Service : ' service.')
end
end
end else
Error_Services('Add', 'AccountID argument was missing in the ' : Service : ' service.')
end
Response = jsonWebAccounts
end service
//----------------------------------------------------------------------------------------------------------------------
// ConvertJSONWebAccountsToMV
//
// Converts a serialized JSON WebAccounts object into a MultiValue formatted WebAccounts row and returns the result.
//----------------------------------------------------------------------------------------------------------------------
Service ConvertJSONWebAccountsToMV(jsonWebAccounts)
mvWebAccounts = ''
If jsonWebAccounts NE '' then
If SRP_JSON(objJSONWebAccounts, 'Parse', jsonWebAccounts) EQ '' then
AccountID = SRP_JSON(objJSONWebAccounts, 'GetValue', 'id')
mvWebAccounts = WebAccounts_Services('GetWebAccounts', AccountID, False$)
If Error_Services('NoError') then
mvWebAccounts<WEB_ACCOUNTS.NAME$> = SRP_JSON(objJSONWebAccounts, 'GetValue', 'name')
mvWebAccounts<WEB_ACCOUNTS.CURRENT_PASSWORD$> = SRP_JSON(objJSONWebAccounts, 'GetValue', 'password.value')
CreateDateTime = SRP_JSON(objJSONWebAccounts, 'GetValue', 'password.created')
TMZ = Oconv(SRP_DateTime('Format', SRP_DateTime('Now', True$), "DDD, DD MMM YYYY hh:mm:ss 'GMT'")[-1, 'B '], 'MD2') ; // Get the TimeZone modifier.
CreateDate = Iconv(Field(CreateDateTime, ' ', 2, 3), 'D')
CreateTime = Iconv(Field(CreateDateTime, ' ', 5, 1), 'MT')
thisSeconds = CreateDate * SecondsPerDay$ + CreateTime
thisSeconds += TMZ * SecondsPerHour$
CreateDate = Int(thisSeconds / SecondsPerDay$)
CreateTime = Mod(thisSeconds, SecondsPerDay$)
mvWebAccounts<WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_DATE$> = CreateDate
mvWebAccounts<WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_TIME$> = CreateTime
ExpireDateTime = SRP_JSON(objJSONWebAccounts, 'GetValue', 'password.expires')
ExpireDate = Iconv(Field(ExpireDateTime, ' ', 2, 3), 'D')
ExpireTime = Iconv(Field(ExpireDateTime, ' ', 5, 1), 'MT')
thisSeconds = ExpireDate * SecondsPerDay$ + ExpireTime
thisSeconds += TMZ * SecondsPerHour$
ExpireDate = Int(thisSeconds / SecondsPerDay$)
ExpireTime = Mod(thisSeconds, SecondsPerDay$)
mvWebAccounts<WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_DATE$> = ExpireDate
mvWebAccounts<WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_TIME$> = ExpireTime
SRP_JSON(objJSONWebAccounts, 'Release')
end
end else
Error_Services('Add', 'Error parsing jsonWebAccounts in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'jsonWebAccounts argument was missing in the ' : Service : ' service.')
end
Response = mvWebAccounts
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// GoSubLabel
//
//----------------------------------------------------------------------------------------------------------------------
GoSubLabel:
return

View File

@ -0,0 +1,226 @@
Function Web_Accounts_Actions(Action, CalcColName, FSList, Handle, Name, FMC, Record, Status, OrigRecord, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Web_Accounts_Actions
Description : Handles calculated columns and MFS calls for the current table.
Notes : This function uses @ID, @RECORD, and @DICT to make sure {ColumnName} references work correctly.
If called from outside of a calculated column these will need to be set and restored.
Parameters :
Action [in] -- Name of the action to be taken
CalcColName [in] -- Name of the calculated column that needs to be processed. Normally this should only be
populated when the CalcField action is being used.
FSList [in] -- The list of MFSs and the BFS name for the current file or volume. This is an @SVM
delimited array, with the current MFS name as the first value in the array, and the BFS
name as the last value. Normally set by a calling MFS.
Handle [in] -- The file handle of the file or media map being accessed. Note, this does contain the
entire handle structure that the Basic+ Open statement would provide. Normally set by a
calling MFS.
Name [in] -- The name (key) of the record or file being accessed. Normally set by a calling MFS.
FMC [in] -- Various functions. Normally set by a calling MFS.
Record [in] -- The entire record (for record-oriented functions) or a newly-created handle (for
"get handle" functions). Normally set by a calling MFS.
Status [in/out] -- Indicator of the success or failure of an action. Normally set by the calling MFS but
for some actions can be set by the action handler to indicate failure.
OrigRecord [in] -- Original content of the record being processed by the current action. This is
automatically being assigned by the WRITE_RECORD and DELETE_RECORD actions within
BASE_MFS.
Param1-10 [in/out] -- Additional request parameter holders
ActionFlow [out] -- Used to control the action chain (see the ACTION_SETUP insert for more information.)
Can also be used to return a special value, such as the results of the CalcField
method.
History : (Date, Initials, Notes)
10/30/18 dmb [SRPFW-254] Original programmer.
01/18/20 dmb [SRPFW-296] Update the CURRENT_PASSWORD_CREATED and CURRENT_PASSWORD_EXPIRES calculated
column logic by replacing Utility_DotNet('TIMEZONE') with the SRP_DateTime service (SRP
Utilities 2.1) to avoid localization problems and potential 502 Bad Gateway errors.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert FILE.SYSTEM.EQUATES
$insert ACTION_SETUP
$insert WEB_ACCOUNTS_EQUATES
Declare function SRP_DateTime
If KeyID then GoSub Initialize_System_Variables
Begin Case
Case Action _EQC 'CalculateColumn' ; GoSub CalculateColumn
Case Action _EQC 'READ_RECORD_PRE' ; GoSub READ_RECORD_PRE
Case Action _EQC 'READ_RECORD' ; GoSub READ_RECORD
Case Action _EQC 'READONLY_RECORD_PRE' ; GoSub READONLY_RECORD_PRE
Case Action _EQC 'READONLY_RECORD' ; GoSub READONLY_RECORD
Case Action _EQC 'WRITE_RECORD_PRE' ; GoSub WRITE_RECORD_PRE
Case Action _EQC 'WRITE_RECORD' ; GoSub WRITE_RECORD
Case Action _EQC 'DELETE_RECORD_PRE' ; GoSub DELETE_RECORD_PRE
Case Action _EQC 'DELETE_RECORD' ; GoSub DELETE_RECORD
Case Otherwise$ ; Status = 'Invalid Action'
End Case
If KeyID then GoSub Restore_System_Variables
Return ActionFlow OR ACTION_CONTINUE$
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calculated Columns
//
// The typical structure of a calculated column will look like this:
//
// Declare function Database_Services
//
// @ANS = Database_Services('CalculatedColumn')
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CalculateColumn:
// Make sure the ActionFlow return variable is cleared in case nothing is calculated.
ActionFlow = ''
Begin Case
Case CalcColName EQ 'CURRENT_PASSWORD_CREATED' ; GoSub CURRENT_PASSWORD_CREATED
Case CalcColName EQ 'CURRENT_PASSWORD_EXPIRES' ; GoSub CURRENT_PASSWORD_EXPIRES
End Case
return
CURRENT_PASSWORD_CREATED:
Created = Iconv(Oconv({CURRENT_PASSWORD_CREATE_DATE}, 'D4/') : ' ' : Oconv({CURRENT_PASSWORD_CREATE_TIME}, 'MTS'), 'DTS')
Created = SRP_DateTime('Format', SRP_DateTime('ToUTC', Created), "DDD, DD MMM YYYY hh:mm:ss 'GMT'")
ActionFlow = Created
return
CURRENT_PASSWORD_EXPIRES:
Expires = Iconv(Oconv({CURRENT_PASSWORD_EXPIRE_DATE}, 'D4/') : ' ' : Oconv({CURRENT_PASSWORD_EXPIRE_TIME}, 'MTS'), 'DTS')
Expires = SRP_DateTime('Format', SRP_DateTime('ToUTC', Expires), "DDD, DD MMM YYYY hh:mm:ss 'GMT'")
ActionFlow = Expires
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MFS Actions
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
READ_RECORD_PRE:
// In order to stop a record from being read in this action these lines of code must be used:
//
// OrigFileError = 100 : @FM : KeyID
// Status = 0
// Record = ''
// ActionFlow = ACTION_STOP$
return
READ_RECORD:
// In order to stop a record from being read in this action these lines of code must be used:
//
// OrigFileError = 100 : @FM : KeyID
// Status = 0
// Record = ''
return
READONLY_RECORD_PRE:
// In order to stop a record from being read in this action these lines of code must be used:
//
// OrigFileError = 100 : @FM : KeyID
// Status = 0
// Record = ''
// ActionFlow = ACTION_STOP$
return
READONLY_RECORD:
// In order to stop a record from being read in this action these lines of code must be used:
//
// OrigFileError = 100 : @FM : KeyID
// Status = 0
// Record = ''
return
WRITE_RECORD_PRE:
return
WRITE_RECORD:
return
DELETE_RECORD_PRE:
return
DELETE_RECORD:
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Initialize_System_Variables:
// Save these for restoration later
SaveDict = @DICT
SaveID = @ID
SaveRecord = @RECORD
OrigFileError = @FILE.ERROR
// Now make sure @DICT, ID, and @RECORD are populated
CurrentDictName = ''
If @DICT then
DictHandle = @DICT<1, 2>
Locate DictHandle in @TABLES(5) Using @FM Setting fPos then
CurrentDictName = Field(@TABLES(0), @FM, fPos, 1)
end
end
If CurrentDictName NE DictName then
Open DictName to @DICT else Status = 'Unable to initialize @DICT'
end
@ID = KeyID
If Record else
// Record might not have been passed in. Read the record from the database table just to make sure.
@FILE.ERROR = ''
Open TableName to hTable then
FullFSList = hTable[1, 'F' : @VM]
BFS = FullFSList[-1, 'B' : @SVM]
LastHandle = hTable[-1, 'B' : \0D\]
FileHandle = \0D\ : LastHandle[1, @VM]
Call @BFS(READO.RECORD, BFS, FileHandle, KeyID, FMC, Record, ReadOStatus)
end
end
@RECORD = Record
return
Restore_System_Variables:
Transfer SaveDict to @DICT
Transfer SaveID to @ID
Transfer SaveRecord to @RECORD
@FILE.ERROR = OrigFileError
return

View File

@ -0,0 +1,133 @@
Compile insert Action_Setup
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Action_Setup
Description : Declarations and equates used by the table action commuters.
Notes : Action_Setup also populates several variables that will often be useful within action handler code.
History : (Date, Initials, Notes)
08/13/10 dmb Original programmer.
09/18/19 dmb Add TableVolumes@ and new Unused global commons in the /Tables/ common block. Remove
dependency upon the Locate statement in @Tables to find the volume of the current table.
- [SRPFW-282]
***********************************************************************************************************************/
Common /Tables/ TableNames@, TableAccounts@, TableHandles@, SysObjHandle@, ActionListHandle@, PromotedListHandle@, NoActionListHandle@, NoPromotedListHandle@, TableVolumes@, Unused10@, Unused11@, Unused12@, Unused13@
Declare function RetStack
// SRP List declarations.
Declare function SRP_List_Create, SRP_List_CreateFromFastArray, SRP_List_Count, SRP_List_GetAt, SRP_List_GetVariable, SRP_List_Locate
Declare subroutine SRP_List_Add, SRP_List_InsertAt, SRP_List_Release, SRP_List_RemoveAt, SRP_List_SetAt
// Initialize handles if necessary.
// The handle to SYSOBJ is formatted for use with MFS/BFS calls.
If Len(SysObjHandle@) else Open 'SYSOBJ' to SysObjHandle@ then SysObjHandle@ = SysObjHandle@<0, 2>
If Len(ActionListHandle@) else ActionListHandle@ = SRP_List_Create()
If Len(PromotedListHandle@) else PromotedListHandle@ = SRP_List_Create()
If Len(NoActionListHandle@) else NoActionListHandle@ = SRP_List_Create()
If Len(NoPromotedListHandle@) else NoPromotedListHandle@ = SRP_List_Create()
// Return values to indicate how the action flow should continue.
Equ ACTION_STOP$ to 0 ; // Action flow should stop
Equ ACTION_CONTINUE$ to 1 ; // Action flow should continue until a later process changes this value
Equ ACTION_CONTINUE_NO_PROMOTED$ to 2 ; // Action flow should by-pass the promoted (generic) logic but allow the system action to execute
Equ ACTION_CONTINUE_NO_SYSTEM$ to 3 ; // Action flow should execute the promoted (generic) logic but stop the system action from executing
Equ ACTION_SYSTEM_ONLY$ to 4 ; // Action flow should execute the system action only
// Make sure any action parameters which have not been assigned are nulled.
If Assigned(Code) else Code = ''
If Assigned(Action) else Action = ''
If Assigned(CalcColName) else CalcColName = ''
If Assigned(FSList) else FSList = ''
If Assigned(Handle) else Handle = ''
If Assigned(Name) then KeyID = Name
If Assigned(KeyID) else KeyID = ''
If Assigned(FMC) else FMC = ''
If Assigned(Record) else Record = ''
If Assigned(Param1) else Param1 = ''
If Assigned(Param2) else Param2 = ''
If Assigned(Param3) else Param3 = ''
If Assigned(Param4) else Param4 = ''
If Assigned(Param5) else Param5 = ''
If Assigned(Param6) else Param6 = ''
If Assigned(Param7) else Param7 = ''
If Assigned(Param8) else Param8 = ''
If Assigned(Param9) else Param9 = ''
If Assigned(Param10) else Param10 = ''
If Assigned(OrigRecord) else OrigRecord = ''
// Get the program stack
RetStack = RetStack()
// 11 is the code value for the OPEN.FILE primitive. No need to call the following logic since it would be premature.
If Code NE 11 then
// Get the name of the database table if it has already been opened with the OPEN.FILE action.
If Len(Handle) then
// Being called from within the MFS. Most methods will pass in the valid database table handle. This should already
// be stored in the TableHandles@ global common. The associated regular database table name will be found in the
// TableNames@ global common.
Locate Handle in TableHandles@ using @FM Setting fPos then
TableName = TableNames@<fPos>
DictName = 'DICT.' : TableName
AccountName = TableAccounts@<fPos>
Volume = TableVolumes@<fPos>
TableHandle = FSList : @VM : Handle
end else
// If the handle was unable to be located in the TableHandles@ global common, this could be a situation where
// the handle was modified on-the-fly by the calling procedure (such as the MFS stack being manipulated for
// some reason). In this case, loop though each hnadle in TableHandles@ and see if it is contained within the
// handle being passed into the MFS. This isn't as precise, but a match will almost certainly be the correct
// handle.
FoundHandle = 0
NumberHandles = DCount(TableHandles@, @FM)
For fPos = 1 to NumberHandles
CompareHandle = TableHandles@<fPos>
If Index(Handle, CompareHandle, 1) then
FoundHandle = 1
TableName = TableNames@<fPos>
end
Until FoundHandle
Next CompareHandle
If FoundHandle then
DictName = 'DICT.' : TableName
AccountName = TableAccounts@<fPos>
Locate TableName in @Tables(0) using @FM setting fPos then
VolumeName = @Tables(1)<fPos>
BFSType = VolumeName[1, '*']
Volume = VolumeName[Col2() + 1, 99]
end else
Volume = ''
end
TableHandle = FSList : @VM : Handle
end
end
end
If Assigned(TableName) else
// Either the Handle argument wasn't assigned or no match could be found in the TableHandles@ global common.
// Most likely this is because an ACTION commuter is being called directly from a program other than an MFS.
// Therefore the name of the database table will be extracted from the name of the ACTIONS program (which is
// assumed to follow the format <TableName>_ACTIONS.
CurProc = RetStack[1, 'F' : @FM]
TableName = CurProc
Swap '_ACTIONS' with '' in TableName
DictName = 'DICT.' : TableName
AccountName = ''
Volume = ''
Open TableName to TableHandle else TableHandle = ''
end
end

View File

@ -0,0 +1,48 @@
Compile insert API_Setup
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : API_Setup
Description : Sets up the current web API.
Notes : See the comments added below.
History : (Date, Initials, Notes)
11/17/18 dmb Original programmer. - [SRPFW-257]
02/03/19 dmb Update URLSegments logic to exclude the query params that are now returned by the
FullEndpointURL service. - [SRPFW-257]
02/11/19 dmb Add FullEndpointNoQuery variable. This is the same as the FullEndpointURL but strips off the
query params. This will be used by logic that needs the full endpoint and also needs to
append additional segments. - [SRPFW-257]
***********************************************************************************************************************/
Common /Debugging/ DebugFlag@
// Utility services.
Declare function Error_Services, HTTP_Services, HTTP_Resource_Services, RetStack
Declare subroutine Error_Services, HTTP_Services, HTTP_Resource_Services
// The API URL is fixed for any application but should be customized for the application itself. This is not always
// passed into the request correctly, especially if a proxy service or rewrite rules are being used.
APIURL = HTTP_Services('GetAPIRootURL', True$)
// The Full End Point URL indicates the URL submitted by the client.
FullEndpointURL = HTTP_Services('GetFullEndpointURL')
FullEndpointURLNoQuery = FullEndpointURL[1, 'F?']
URLSegments = FullEndpointURLNoQuery
If URLSegments[-1, 1] EQ '/' then URLSegments[-1, 1] = ''
Convert '/' to @FM in URLSegments
NumSegments = DCount(URLSegments, @FM)
ParentURL = Field(FullEndpointURL, '/', 1, NumSegments - 1)
EndpointSegment = URLSegments<NumSegments>
ParentSegment = URLSegments<NumSegments - 1>
// The HTTP method (or verb) submitted by the client.
HTTPMethod = HTTP_Services('GetHTTPRequestMethod')
// Get the name of the current service handler in case it needs to be used for error management.
CurrentAPI = RetStack()<1>

View File

@ -0,0 +1,252 @@
Compile insert App_Inserts
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : App_Inserts
Description : Common declarations and equates used by the application.
Notes : App_Inserts is designed to be the most commonly used insert within SRP FrameWorks routines.
History : (Date, Initials, Notes)
07/23/98 dmb Original programmer.
10/04/13 dmb Added insert for SystemFont$, SystemTypeface$, and SystemPoint$ to make it easier for
commuters to apply the FrameWorks default font. - [SRPFW-17]
***********************************************************************************************************************/
Declare function Msg, PopUp, Set_Property, Get_Property, Utility, Send_Message, Dialog_Box, Start_Window
Declare function Start_MDIChild, Set_Printer, Get_Printer, SRP_Show_Window, MCP, GetTickCount
Declare function Form_Services, Error_Services, Memory_Services, MCP
Declare subroutine Set_Property, Utility, Send_Event, Send_Message, End_Dialog, Send_Info, Msg, SendMessage
Declare subroutine Forward_Event, Lock_Record, Post_Event, SRP_Show_Window, SRP_Set_Prop_Array
Declare subroutine Form_Services, Error_Services, SRP_Stopwatch, Memory_Services, MCP
Equ SystemTable$ to 'APP_INFO'
* Logical equates
$insert LOGICAL
Equ Success$ to 1
Equ Failure$ to 0
Equ Passed$ to 1
Equ Failed$ to 0
Equ Qualified$ to 1
Equ Not_qualified$ to 0
Equ Confirmed$ to 1
Equ Not_confirmed$ to 0
Equ OK$ to 1
* General equates
Equ Tab$ to Char(9)
Equ Esc$ to \1B\
Equ CRLF$ to \0D0A\
Equ Lock$ to 1
Equ Unlock$ to 2
Equ ReadOnly$ to 0
Equ FullWrite$ to 1
Equ NoAccess$ to -1
* Font equates
Equ Tahoma_8_Reg$ to 'Tahoma' : @SVM : -11 : @SVM : 400 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0
Equ Tahoma_8_Reg_UL$ to 'Tahoma' : @SVM : -11 : @SVM : 400 : @SVM : 0 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0
Equ Tahoma_8_Bold$ to 'Tahoma' : @SVM : -11 : @SVM : 700 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0
Equ Tahoma_12_Reg$ to 'Tahoma' : @SVM : 12 : @SVM : 400 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0
Equ Tahoma_12_Reg_UL$ to 'Tahoma' : @SVM : 12 : @SVM : 400 : @SVM : 0 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0
Equ Tahoma_12_Bold$ to 'Tahoma' : @SVM : 12 : @SVM : 700 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0
* Promoted Event equates
Equ Create$ to 1
Equ Activated$ to 2
Equ Read_Pre_System$ to 3
Equ Clear_Post_System$ to 4
Equ Close_Post_System$ to 5
Equ Size$ to 6
Equ Delete_Post_System$ to 7
Equ Winmsg$ to 8
Equ Write_Pre_System$ to 9
Equ Gotfocus$ to 10
Equ Lostfocus$ to 11
Equ Inactivated$ to 12
Equ Read_Post_System$ to 13
Equ Clear_Pre_System$ to 14
Equ Poschanged$ to 15
Equ Close_Pre_System$ to 16
Equ Write_Post_System$ to 17
Equ Delete_Pre_System$ to 18
Equ InsertRow$ to 19
Equ DeleteRow$ to 20
Equ ColSize$ to 21
Equ RightClickUp$ to 22
Equ MouseOver$ to 23
Equ MouseOff$ to 24
Equ OLE$ to 25
Equ Click$ to 26
Equ Timer$ to 27
Equ ContextMenu$ to 28
// General Windows API equates
Equ WM_USER to 1024
Equ WM_CLOSE to 16
Equ WM_COMMAND to 273
Equ WM_LBUTTONDOWN to 513 ; // 0x0201
Equ WM_LBUTTONUP to 514 ; // 0x0202
Equ WM_LBUTTONDBLCLK to 515 ; // 0x0203
Equ WM_RBUTTONDOWN to 516 ; // 0x0204
Equ WM_RBUTTONUP to 517 ; // 0x0205
Equ WM_PARENTNOTIFY to 528 ; // 0x0210
Equ WM_SYSCOLORCHANGE to 21 ; // 0x0015
Equ WM_SETCURSOR to 32 ; // 0x0020
Equ WM_SIZE to 5 ; // 0x0005
Equ WM_MOVE to 3 ; // 0x0003
Equ WM_GETMINMAXINFO to 36 ; // 0x0024
Equ WM_WINDOWPOSCHANGING to 70
// ShowWindow API equates
Equ SW_FORCEMINIMIZE to 11
Equ SW_HIDE to 0
Equ SW_MAXIMIZE to 3
Equ SW_MINIMIZE to 6
Equ SW_RESTORE to 9
Equ SW_SHOW to 5
Equ SW_SHOWDEFAULT to 10
Equ SW_SHOWMAXIMIZED to 3
Equ SW_SHOWMINIMIZED to 2
Equ SW_SHOWMINNOACTIVE to 7
Equ SW_SHOWNA to 8
Equ SW_SHOWNOACTIVATE to 4
Equ SW_SHOWNORMAL to 1
Equ WS_CAPTION$ to 0x00C00000
Equ WS_SYSMENU$ to 0x00080000
Equ WS_THICKFRAME$ to 0x00040000
Equ WS_EX_TOOLWINDOW$ to 0x00000080
Equ WS_EX_CLIENTEDGE$ to 0x200
Equ WS_CLIPCHILDREN$ to 0x02000000
Equ SM_CYCAPTION$ to 4
Equ F4_VK_CODE to 115 ; // 115 is the virtual key code for F4.
Equ TAB_VK_CODE to 9
* Edittable/Datatable equates
Equ DTN_ABORTEDIT to 17
Equ DTM_EDITCURCELL to WM_USER + 95 ; * Change to Edit mode now
Equ DTM_SETEDITKEY to 1118 ; * Set key to change to Edit Mode
Equ DTM_SETCOLFORMAT to WM_USER + 18
Equ DT_BEGINEDIT to 1 ;* begin edit mode
Equ DT_ENDEDIT to 2 ;* end the edit
Equ DT_ABORTEDIT to 3 ;* Esc will undo changes
Equ DTS_EDIT to 4
Equ DTCS_PROTECT to 8
* Help equates
Equ HELP_CONTEXT to 1
Equ HELP_QUIT to 2
Equ HELP_INDEX to 3
Equ HELP_CONTENTS to 3
Equ HELP_HELPONHELP to 4
Equ HELP_SETINDEX to 5
Equ HELP_SETCONTENTS to 5
Equ HELP_CONTEXTPOPUP to 8
Equ HELP_FORCEFILE to 9
Equ HELP_KEY to 257
Equ HELP_COMMAND to 258
Equ HELP_PARTIALKEY to 261
Equ HELP_MULTIKEY to 513
Equ HELP_SETWINPOS to 515
* Color equates
Equ Msg_Light_Grey$ to 212:@VM:208:@VM:200
Equ Msg_Dark_Grey$ to 127:@VM:127:@VM:127
Equ Msg_Light_Blue$ to 0:@VM:255:@VM:255
Equ Msg_Dark_Blue$ to 0:@VM:0:@VM:255
Equ Msg_Red$ to 255:@VM:0:@VM:0
Equ Msg_Green$ to 0:@VM:255:@VM:0
Equ Msg_Purple$ to 255:@VM:0:@VM:255
Equ Msg_Yellow$ to 255:@VM:255:@VM:0
Equ Msg_Black$ to 0:@VM:0:@VM:0
Equ Msg_White$ to 255:@VM:255:@VM:255
* RGB colors
EQU USEPARENT$ TO 0 ;* \000000\
EQU BLACK$ TO 1 ;* \FFFFFF\
EQU RED$ TO 255 ;* \0000FF\
EQU ORANGE$ TO 33023 ;* \0080FF\
EQU GREEN$ TO 65280 ;* \00FF00\
EQU YELLOW$ TO 65535 ;* \00FFFF\
EQU GREY$ TO 12632256 ;* \C0C0C0\
EQU BLUE$ TO 16711680 ;* \FF0000\
EQU PURPLE$ TO 16711808 ;* \FF0080\
EQU MAGENTA$ TO 16711935 ;* \FF00FF\
EQU CYAN$ TO 16776960 ;* \FFFF00\
EQU WHITE$ TO 16777215 ;* \FFFFFF\
// The following color equates are used directly
// Example: Set_Property(CtrlEntID, "BACKCOLOR", COLOR_BTNFACE$)
EQU COLOR_SCROLLBAR$ TO 2147483648 ;* \80000000\
EQU COLOR_BACKGROUND$ TO 2164260864 ;* \81000000\
EQU COLOR_ACTIVECAPTION$ TO 2181038080 ;* \82000000\
EQU COLOR_INACTIVECAPTION$ TO 2197815296 ;* \83000000\
EQU COLOR_MENU$ TO 2214592512 ;* \84000000\
EQU COLOR_WINDOW$ TO 2231369728 ;* \85000000\
EQU COLOR_WINDOWFRAME$ TO 2248146944 ;* \86000000\
EQU COLOR_MENUTEXT$ TO 2264924160 ;* \87000000\
EQU COLOR_WINDOWTEXT$ TO 2281701376 ;* \88000000\
EQU COLOR_CAPTIONTEXT$ TO 2298478592 ;* \89000000\
EQU COLOR_ACTIVEBORDER$ TO 2315255808 ;* \8A000000\
EQU COLOR_INACTIVEBORDER$ TO 2332033024 ;* \8B000000\
EQU COLOR_APPWORKSPACE$ TO 2348810240 ;* \8C000000\
EQU COLOR_HIGHLIGHT$ TO 2365587456 ;* \8D000000\
EQU COLOR_HIGHLIGHTTEXT$ TO 2382364672 ;* \8E000000\
EQU COLOR_BTNFACE$ TO 2399141888 ;* \8F000000\
EQU COLOR_BTNSHADOW$ TO 2415919104 ;* \90000000\
EQU COLOR_GRAYTEXT$ TO 2432696320 ;* \91000000\
EQU COLOR_BTNTEXT$ TO 2449473536 ;* \92000000\
EQU COLOR_INACTIVECAPTIONTEXT$ TO 2466250752 ;* \93000000\
EQU COLOR_BTNHIGHLIGHT$ TO 2483027968 ;* \94000000\
// The following color equates are used with the GetSysColor WinAPI command
// Example: Set_Property(CtrlEntID, "BACKCOLOR", GetSysColor(API_COLOR_BTNFACE$))
Equ API_COLOR_SCROLLBAR$ To 0
Equ API_COLOR_BACKGROUND$ To 1
Equ API_COLOR_ACTIVECAPTION$ To 2
Equ API_COLOR_INACTIVECAPTION$ To 3
Equ API_COLOR_MENU$ To 4
Equ API_COLOR_WINDOW$ To 5
Equ API_COLOR_WINDOWFRAME$ To 6
Equ API_COLOR_MENUTEXT$ To 7
Equ API_COLOR_WINDOWTEXT$ To 8
Equ API_COLOR_CAPTIONTEXT$ To 9
Equ API_COLOR_ACTIVEBORDER$ To 10
Equ API_COLOR_INACTIVEBORDER$ To 11
Equ API_COLOR_APPWORKSPACE$ To 12
Equ API_COLOR_HIGHLIGHT$ To 13
Equ API_COLOR_HIGHLIGHTTEXT$ To 14
Equ API_COLOR_BTNFACE$ To 15
Equ API_COLOR_BTNSHADOW$ To 16
Equ API_COLOR_GRAYTEXT$ To 17
Equ API_COLOR_BTNTEXT$ To 18
Equ API_COLOR_INACTIVECAPTIONTEXT$ To 19
Equ API_COLOR_BTNHIGHLIGHT$ To 20
// Preference Manager
Equ ImagePath$ to Memory_Services('GetValue', 'PM_CURRENT_IMAGE_PATH') : '\'
PMSystemFont = Memory_Services('GetValue', 'PM_SYSTEM_FONT')
Convert ',' to @SVM in PMSystemFont
Equ SystemFont$ to PMSystemFont
Equ SystemTypeface$ to SystemFont$[1, @SVM]
Equ SystemPoint$ to SystemFont$[Col2() + 1, @SVM]

View File

@ -0,0 +1,36 @@
Compile insert CONTACTS_EQUATES
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : CONTACTS_EQUATES
Description : Equates used by any service that works with the CONTACTS database table.
Notes :
History : (Date, Initials, Notes)
07/06/17 dmb Original programmer. - [SRPFW-187]
***********************************************************************************************************************/
Equ CONTACTS_CONTACT_ID$ To 0
Equ CONTACTS_MODIFIED_BY$ To 1
Equ CONTACTS_MODIFIED_DATE$ To 2
Equ CONTACTS_MODIFIED_TIME$ To 3
Equ CONTACTS_FIRST_NAME$ To 4
Equ CONTACTS_LAST_NAME$ To 5
Equ CONTACTS_ADDRESS$ To 6
Equ CONTACTS_CITY$ To 7
Equ CONTACTS_STATE$ To 8
Equ CONTACTS_ZIP$ To 9
Equ CONTACTS_COUNTY$ To 10
Equ CONTACTS_PHONE_TYPE$ To 11
Equ CONTACTS_PHONE_NUMBER$ To 12
Equ CONTACTS_EMAIL$ To 13
Equ CONTACTS_COMPANY$ To 14
Equ CONTACTS_URL$ To 15
Equ CONTACTS_BIRTHDATE$ To 16
Equ CONTACTS_PICTURE$ To 17
Equ CONTACTS_NOTES$ To 18

View File

@ -0,0 +1,99 @@
Compile insert Event_Setup
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Event_Setup
Description : Declarations and equates used by the form event commuters.
Notes : Event_Setup also populates several variables that will often be useful within event handler code.
History : (Date, Initials, Notes)
08/13/10 dmb Original programmer.
***********************************************************************************************************************/
Declare function Get_Property, Set_Property, Get_Current_Event, Get_Window_ID, Get_Record
// Return values to indicate how the event flow should continue.
Equ EVENT_STOP$ to 0 ; // Event flow should stop
Equ EVENT_CONTINUE$ to 1 ; // Event flow should continue until a later process changes this value
Equ EVENT_CONTINUE_NO_PROMOTED$ to 2 ; // Event flow should by-pass the promoted (generic) logic but allow the system event handler to execute
Equ EVENT_CONTINUE_NO_SYSTEM$ to 3 ; // Event flow should execute the promoted (generic) logic but stop the system event handler from executing
Equ EVENT_SYSTEM_ONLY$ to 4 ; // Event flow should execute the system event handler only (normal option for third-party windows running in FrameWorks)
// Make sure any event parameters which have not been assigned are nulled.
If Assigned(CtrlEntId) else CtrlEntId = ''
If Assigned(Event) else Event = ''
If Assigned(Param1) else Param1 = ''
If Assigned(Param2) else Param2 = ''
If Assigned(Param3) else Param3 = ''
If Assigned(Param4) else Param4 = ''
If Assigned(Param5) else Param5 = ''
If Assigned(Param6) else Param6 = ''
If Assigned(Param7) else Param7 = ''
If Assigned(Param8) else Param8 = ''
If Assigned(Param9) else Param9 = ''
If Assigned(Param10) else Param10 = ''
If Assigned(Param11) else Param11 = ''
If Assigned(Param12) else Param12 = ''
If Assigned(Param13) else Param13 = ''
If Assigned(Param14) else Param14 = ''
If Assigned(Param15) else Param15 = ''
// Get the design time name of the window in case this is a multi-instance window.
Window = @Window[1, 'F*']
MDIFrame = Get_Property(@Window, 'MDIFRAME')
Parent = Get_Property(@Window, 'PARENT')
If MDIFrame EQ '' then MDIFrame = Parent ; // Dialog boxes won't set the MDIFRAME property so use the PARENT property.
// Always get the CtrlClassID since we are not passing it through the event parameters.
CtrlClassId = Get_Property(CtrlEntId, 'TYPE')
// Get the name of the control on the window based on the CtrlClassId.
Begin Case
Case CtrlClassId EQ 'WINDOW'
Control = Window
Case CtrlClassId EQ 'RADIOBUTTON'
Control = Field(CtrlEntId, '.', 2, 2)
Case CtrlClassId EQ 'MENU'
Control = CtrlEntId[-1, 'B.']
Case 1
Control = Field(CtrlEntId, '.', 2, 1)
End Case
// If this is an OLE control, get the ProgID.
ProgID = ''
If CtrlClassId EQ 'OLECONTROL' then ProgID = Get_Property(CtrlEntId, 'ORIG_TEXT')
// Get the Event Type so generic event functionality can be executed properly.
EventType = Get_Current_Event()
// Combine the event type and control into an event action.
If EventType EQ 'OLE' then
// Because the Promoted_Events function transfers parameters, this will only appear correctly in a commuter module.
EventAction = Event : '.' : Control
end else
EventAction = EventType : '.' : Control
end
// Get the current window's key ID. Strip off the @SVM if this window is ignoring self-locks.
KeyID = Get_Property(@Window, 'ID')[1, 'F' : @SVM]
// If KeyID is null then check to see if the key controls are populated. If so, then this is probably a locked record.
// ID properties are null with locked records.
If KeyID EQ '' then
KeyID = Get_Window_ID(@Window)
end
// Get the current window's record.
Record = Get_Property(@Window, 'ATRECORD')
// If the window uses QuickEvents to call the commuter module, check for @EVENT in the event parameter. This is here for
// backwards compatability. OpenInsight 7.1 and higher automatically swaps @EVENT with the actual event. Prior versions
// of OpenInsight will just pass the literal through. Therefore, this will swap out @EVENT with the actual event.
If Event EQ '@EVENT' then Swap '@EVENT' with EventType in Event

View File

@ -0,0 +1,131 @@
Compile insert HTTP_Framework_Setup_Equates
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Framework_Setup_Equates
Description :
Notes : The SRP HTTP Framework stores configuration settings in the SYSENV\SRP_HTTP_FRAMEWORK_SETUP[*AppID]
record. These equates define the meaning of each value and can be used in routines that read/write
data to this configuration record.
History : (Date, Initials, Notes)
11/07/16 dmb Original programmer.
01/01/17 dmb [SRPFW-116] Added HTTP_FRAMEWORK_SETUP_FLUSH_CACHE$.
02/03/17 dmb [SRPFW-132] Added HTTP_FRAMEWORK_SETUP_NON_AUTHENTICATED_URLS$.
02/27/17 dmb [SRPFW-125] Added HTTP_FRAMEWORK_SETUP_ABORTED_SERVICE$.
03/04/17 dmb [SRPFW-154] Added HTTP_FRAMEWORK_SETUP_ENABLE_LOGGING$.
03/07/17 dmb [SRPFW-155] Added HTTP_FRAMEWORK_SETUP_DEBUGGER_SETTING$ and
HTTP_FRAMEWORK_SETUP_DEBUGGER_INTERCEPT$.
07/07/17 dmb [SRPFW-154] Added HTTP_FRAMEWORK_SETUP_LOG_ERRORS_ONLY$.
10/22/18 dmb [SRPFW-253] Added HTTP_FRAMEWORK_SETUP_WHITELISTED_IPS$.
11/01/18 dmb [SRPFW-255] Added HTTP_FRAMEWORK_SETUP_ENABLE_HTTP_BASIC_AUTHENTICATION$.
11/01/18 dmb [SRPFW-255] Added HTTP_FRAMEWORK_SETUP_NEW_PASSWORD_TIME_TO_LIVE$.
11/01/18 dmb [SRPFW-255] Added HTTP_FRAMEWORK_SETUP_OLD_PASSWORD_TIME_TO_LIVE$.
11/01/18 dmb [SRPFW-256] Added HTTP_FRAMEWORK_SETUP_INVALID_PASSWORD_LIMIT$.
11/01/18 dmb [SRPFW-256] Added HTTP_FRAMEWORK_SETUP_CONTAINMENT_ACTION$.
11/05/18 dmb [SRPFW-257] Added ResourcesKeyID$ equate.
11/18/18 dmb [SRPFW-257] Added HTTP_FRAMEWORK_SETUP_API_CALL_PROCEDURE$.
11/18/18 dmb [SRPFW-257] Added Equ APISignatureKeyID$.
11/18/18 dmb [SRPFW-257] Added Equ APICommentBlockKeyID$.
11/18/18 dmb [SRPFW-257] Added Equ APIBodyBlockKeyID$.
09/23/19 dmb [SRPFW-278] Added Equ ArchiveScriptKeyID$.
06/15/20 dmb [SRPFW-313] Added HTTP_FRAMEWORK_SETUP_NON_AUTHENTICATED_PATHS$ as a synonym for
HTTP_FRAMEWORK_SETUP_NON_AUTHENTICATED_URLS$ (which is being deprecated).
06/15/20 dmb [SRPFW-313] Added HTTP_FRAMEWORK_SETUP_NON_AUTHENTICATED_QUERY_PARAMS$.
06/30/20 dmb [SRPFW-313] Added HTTP_FRAMEWORK_SETUP_BANNED_IPS$.
06/30/20 dmb [SRPFW-313] Added HTTP_FRAMEWORK_SETUP_WHITELISTED_IPS_TYPE$
***********************************************************************************************************************/
Equ EVENT_CONTINUE$ to 1
Equ EVENT_STOP$ to 0
Equ ApplicationPath$ to Drive()
Equ SetupTable$ to 'SYSENV'
Equ SetupRowKeyID$ to 'SRP_HTTP_FRAMEWORK_SETUP'
Equ ResourcesKeyID$ to 'SRP_HTTP_FRAMEWORK_RESOURCES'
Equ APISignatureKeyID$ to 'SRP_HTTP_FRAMEWORK_TEMPLATE_API_SIGNATURE'
Equ APICommentBlockKeyID$ to 'SRP_HTTP_FRAMEWORK_TEMPLATE_API_COMMENT_BLOCK'
Equ APIBodyBlockKeyID$ to 'SRP_HTTP_FRAMEWORK_TEMPLATE_API_BODY'
Equ ArchiveScriptKeyID$ to 'SRP_HTTP_FRAMEWORK_HTTP_LOGS_ARCHIVE_SCRIPT'
// Identifies the primary URL of the website, e.g., www.mywebsite.com.
Equ HTTP_FRAMEWORK_SETUP_HOME_URL$ to 1
// Identifies the path that is appended to the Home URL wherein the entry point of the API begins, e.g., /api
//
// The HTTP_Service_Setup uses the above information to create proper RESTful responses wherein paths to other
// web service APIs need to be included within the response. Thus, in the above examples, the two are joined
// when creating fully resolved API URLs, e.g., www.mywebsite.com/api/<service>
Equ HTTP_FRAMEWORK_SETUP_API_URL$ to 2
// Used in HTTP_MCP to identify the local OS path where request and response content can be saved for off-line
// analysis. If the path does not exist, then no attempt to store this information will be made.
Equ HTTP_FRAMEWORK_SETUP_CAPTURE_PATH$ to 3
// Boolean setting that determines if authentication is enabled. Used by HTTP_Authentication_Services.
// Note: Only an explicit value of 0 (False) will disable authentication. Any other value, including an empty
// value, will enable authentication.
Equ HTTP_FRAMEWORK_SETUP_ENABLE_AUTHENTICATION$ to 4
// Used with HTTP authentication to associate resource links to the same protective space.
Equ HTTP_FRAMEWORK_SETUP_REALM_VALUE$ to 5
// Name of the entry point web service. This is used by HTTP_MCP to call the first web service. This should not
// include the standard HTTP prefix or SERVICES suffix. The default value is entry_point.
Equ HTTP_FRAMEWORK_SETUP_ENTRY_POINT_SERVICE$ to 6
// Boolean setting that determines if code should be flushed when the web service is finished. This allows changes
// in web service procedures to always be available without having to restart the OEngineServer.
Equ HTTP_FRAMEWORK_SETUP_FLUSH_CACHE$ to 7
// @VM list of Paths that should not be authenticated. This includes Paths that support OAuth redirects since these
// requests will unlikely be authenticated (although they should be secret and secure with the OAuth authenticating
// server).
Equ HTTP_FRAMEWORK_SETUP_NON_AUTHENTICATED_URLS$ to 8
Equ HTTP_FRAMEWORK_SETUP_NON_AUTHENTICATED_PATHS$ to 8
// Service handler for HTTP Requests that get aborted either due to Runtime Errors or Status Errors. If the Debugger
// Intercept has been enabled, this handler will only receive Status Error aborts.
Equ HTTP_FRAMEWORK_SETUP_ABORTED_SERVICE$ to 9
// Boolean setting that determines if logging is enabled. This is used by the CreateLogFile service.
// Note: Only an explicit value of 0 (False) will disable logging. Any other value, including an empty
// value, will enable logging.
Equ HTTP_FRAMEWORK_SETUP_ENABLE_LOGGING$ to 10
// Debugger Setting value that will be passed into the RTI_Debugger_Setting subroutine. 0=Disabled, 1=Enabled, and
// 2=Intercept. If value is 2, the value of HTTP_FRAMEWORK_SETUP_DEBUGGER_INTERCEPT$ will be used to determine the
// name of the intercept stored procedure.
Equ HTTP_FRAMEWORK_SETUP_DEBUGGER_SETTING$ to 11
// Service handler for HTTP Requests that abort due to a Runtime Error and the Debugger Intercept has been enabled.
// See HTTP_FRAMEWORK_SETUP_DEBUGGER_SETTING$.
Equ HTTP_FRAMEWORK_SETUP_DEBUGGER_INTERCEPT$ to 12
// Boolean setting that determines if only error responses (i.e., status codes of 4xx or 5xx) should be logged. This is
// used by the CreateLogFile service. Note: Only an explicit value of 0 (False) will disable logging. Any other value,
// including an empty value, will enable logging.
Equ HTTP_FRAMEWORK_SETUP_LOG_ERRORS_ONLY$ to 13
// @VM list of IPs that should be permitted. If this list is empty, then all IPs are permitted. Note, a valid IP does
// not automatically mean the request is authenticated. That is a separate check.
Equ HTTP_FRAMEWORK_SETUP_WHITELISTED_IPS$ to 14
// Boolean setting that determines if HTTP Basic Authentication is enabled. Used by HTTP_Authentication_Services. This
// is ignored if the Enable Authentication flag is set to False.
Equ HTTP_FRAMEWORK_SETUP_ENABLE_HTTP_BASIC_AUTHENTICATION$ to 15
// If HTTP Basic Authentication is enabled, this is how long (in hours) new passwords that are created can be valid
// before needing to be reset. If left empty, passwords do not expire.
Equ HTTP_FRAMEWORK_SETUP_NEW_PASSWORD_TIME_TO_LIVE$ to 16
// If HTTP Basic Authentication is enabled, this is how long (in hours) old passwords can remain valid. This should be a
// short period of time allowing for the new password to propogate. If left empty, old passwords will only be valid for
// 1 hour.
Equ HTTP_FRAMEWORK_SETUP_OLD_PASSWORD_TIME_TO_LIVE$ to 17
// If HTTP Basic Authentication is enabled, this is how many attempts to access the system with an invalid password will
// be allowed before containment action is taken.
Equ HTTP_FRAMEWORK_SETUP_INVALID_PASSWORD_LIMIT$ to 18
// If HTTP Basic Authentication is enabled, this determines the containment action to take when the number of invalid
// password attempts has been exceeded.
Equ HTTP_FRAMEWORK_SETUP_CONTAINMENT_ACTION$ to 19
// The type of method used to call the API.
Equ HTTP_FRAMEWORK_SETUP_API_CALL_PROCEDURE$ to 20
// @VM/@TM delimited list of query params that should be used to further define which URL paths should be
// non-authenticated.
Equ HTTP_FRAMEWORK_SETUP_NON_AUTHENTICATED_QUERY_PARAMS$ to 21
// @VM list of IPs that should be banned.
Equ HTTP_FRAMEWORK_SETUP_BANNED_IPS$ to 22
// Flag to determine if Whitelisted IPs should represent only those IPs that will be permitted (default) or if
// Whitelisted IPs should always be permitted (i.e., do not require other forms of authentication). Empty value or 1
// means restriced IP access, 2 means IPs are always permitted.
Equ HTTP_FRAMEWORK_SETUP_WHITELISTED_IPS_TYPE$ to 23

View File

@ -0,0 +1,28 @@
Compile insert HTTP_Inserts
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Inserts
Description : Declares and equates used by HTTP services.
Notes :
History : (Date, Initials, Notes)
02/06/15 dmb Original programmer. - [SRPFW-77]
02/16/15 dmb Add HTTP_Services in the declaration list. - [SRPFW-83]
02/27/16 dmb Add SRP_Hash in the declaration list. - [SRPFW-112]
***********************************************************************************************************************/
// Utility services.
Declare function Namecap, HexConv, Run_OECGI_Request
Declare function SRP_Extract_XML, SRP_Encode, SRP_Decode, SRP_Hash
Declare function HTTP_JSON_Services, HTTP_Services, SRP_JSON
Declare subroutine HTTP_JSON_Services, HTTP_Services, SRP_JSON
// Application services.
Declare function HTTP_Authentication_Services
Declare subroutine HTTP_Authentication_Services, HTTP_Entry_Point_Services

View File

@ -0,0 +1,54 @@
Compile insert HTTP_Service_Setup
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : HTTP_Service_Setup
Description : Sets up the current HTTP service by parsing the current URL as needed.
Notes : See the comments added below.
History : (Date, Initials, Notes)
02/25/15 dmb Original programmer. - [SRPFW-84]
02/22/16 dmb Swap hardcoded URL equates with Xlates from SYSENV\SRP_HTTP_FRAMEWORK_SETUP configuration
record. - [SRPFW-103]
02/23/16 dmb Add a work-around fix for IIS web server requests. - [SRPFW-102]
02/25/16 dmb Replace Xlates into SYSENV\SRP_HTTP_FRAMEWORK_SETUP with GetHomeURL and GetAPIRootURL
services. - [SRPFW-108]
03/09/16 dmb Refactor code to be more streamlined. Remove several lines of code and optimize for changes
to the RunHTTPService service. - [SRPFW-112]
***********************************************************************************************************************/
Common /Debugging/ DebugFlag@
// Utility services.
Declare function Error_Services, HTTP_Services, HTTP_Resource_Services, RetStack
Declare subroutine Error_Services, HTTP_Services, HTTP_Resource_Services
// The API URL is fixed for any application but should be customized for the application itself. This is not always
// passed into the request correctly, especially if a proxy service or rewrite rules are being used.
APIURL = HTTP_Services('GetAPIRootURL', True$)
// The Full End Point URL indicates the URL submitted by the client.
FullEndPointURL = HTTP_Services('GetFullEndPointURL')
// The HTTP method (or verb) submitted by the client.
HTTPMethod = HTTP_Services('GetHTTPRequestMethod')
// The Self URL represents the Full End Point URL up to the current segment. This often used in hypermedia responses
// so clients know how to trace back.
LenRemainingURL = Len(RemainingURL)
LenFullEndPointURL = Len(FullEndPointURL)
SelfURL = FullEndPointURL[1, (LenFullEndPointURL - LenRemainingURL)]
If SelfURL[-1, 1] = '/' then SelfURL[-1, 1] = ''
HTTP_Services('SetSelfURL', SelfURL)
// The Next Segment is the segment in the URL path that will come immediately after the current segment. This could
// represent another service or it could represent an Item ID for the current service/resource.
NextSegment = RemainingURL[1, '/']
// Get the name of the current service handler in case it needs to be used for error management.
CurrentServiceHandler = RetStack()<1>

View File

@ -0,0 +1,77 @@
compile insert Inet_Equates
* CGI enviromental variables (see source\oinsight\c\oicgi\request.h)
equ QUERY_STRING$ to 1
equ PATH_INFO$ to 2
equ CONTENT_TYPE$ to 3
equ CONTENT_LENGTH$ to 4
equ GATEWAY_INTERFACE$ to 5
equ HTTPS$ to 6
equ HTTP_ACCEPT$ to 7
equ HTTP_COOKIE$ to 8
equ HTTP_FROM$ to 9
equ HTTP_REFERER$ to 10
equ HTTP_USER_AGENT$ to 11
equ PATH_TRANSLATED$ to 12
equ REMOTE_ADDR$ to 13
equ REMOTE_HOST$ to 14
equ REMOTE_IDENT$ to 15
equ REMOTE_USER$ to 16
equ REQUEST_METHOD$ to 17
equ SCRIPT_NAME$ to 18
equ SERVER_NAME$ to 19
equ SERVER_PORT$ to 20
equ SERVER_PROTOCOL$ to 21
equ SERVER_SOFTWARE$ to 22
equ SERVER_URL$ to 23
equ NOURLDECODE$ to 24 ; * // Mr C, Added 7th November 2003
equ RESPONSE_IS_BINARY$ to 25 ; * // Mr C, Added 15th March 2006
Equ REGISTRY_SETTINGS$ To 26 ;* bzs 031706
* BZS 031813 Added for OECGI4+
Equ OECGI_VERSION$ To 27
Equ GET_STRING$ To 28
Equ POST_STRING$ To 29
Equ ADDITIONAL_VALUES_STRING$ TO 30
* BZS 042419 Added for encryption
Equ ENCODING_STRING$ To 31
* Gateway Services Monitor window name
equ GS_MONITOR$ to 'INET_GATEWAY'
* OMNIEVENT calls
equ INCOMING$ to 'INCOMING' ;* Param1 = request
equ OUTCOMING$ to 'OUTCOMING' ;* Param1 = response
equ INPROGRESS$ to 'INPROGRESS' ;* Param1 = time left before timeout (in secs)
* persistent configuration information
equ CFG_TABLE$ to "SYSENV"
equ CFG_KEY$ to "CFG_INET"
* fields in CFG_INET
equ CFG_CALLBACK$ to 1
equ CFG_ERRTEXT$ to 2
Equ CFG_DEFAULTS$ To 3 ;* bzs 061209
Equ CFG_QUERYPARAM_FLAG$ To 4 ;* BZS 060311
Equ CFG_INET_WHITELIST$ To 5 ;* bzs 061711
Equ CFG_TYPE_COMPRESSION$ To 6 ;* bzs 042419
Equ CFG_TYPE_COMPRESSION_DEFAULT$ To "deflate":@VM:"gzip" ;* bzs 042419 what we support, in the preferred order
Equ CFG_MIN_COMPRESSION$ To 7 ;* bzs 042419
Equ CFG_MIN_COMPRESSION_DEFAULT$ To 1000 ;* bzs 042419
* values in CFG_INET<CFG_CALLBACK$>
equ CFG_FN_SECURITY$ to 1 ;* a la INET_SECURITY
equ CFG_FN_FINALIZE$ to 2 ;* a la INET_FINALIZE
equ CFG_FN_ABORTED$ to 3 ;* errtext=() - called when an inet procedure has crashed and the gateway recovers
equ CFG_FN_WHITELIST$ to 4 ;* a la INET_WHITELIST
Equ CFG_FN_HANDLER$ To 5 ;* bzs 031517 RESTful processing routine, if applicable
* values in CFG_INET<CFG_ERRTEXT$> (multiple lines @tm-delim'd)
equ CFG_ERR_NORESULT$ to 1
* bzs 061209 values in CFG_INET<CFG_DEFAULTS$>
Equ CFG_DEF_CGI$ To 1 ; * a la ".CGI"
Equ CFG_DEF_PAGE$ To 2 ; * a la "/login"

View File

@ -0,0 +1,15 @@
compile insert INVOICES_EQUATES
/*----------------------------------------
Author : Table Create Insert Routine
Written : 13/02/2020
Description : Insert for Table INVOICES
----------------------------------------*/
Equ INVOICES.INVOICE_NO$ To 0
Equ INVOICES.CLIENT_NO$ To 1
Equ INVOICES.INVOICE_DATE$ To 2
Equ INVOICES.SHIPPING_DESTINATION$ To 3
Equ INVOICES.CONTACTS$ To 4
Equ INVOICES.PHONE_NUMBERS$ To 5
Equ INVOICES.TERMS$ To 6

View File

@ -0,0 +1,43 @@
Compile Insert Menu_Equates
* // These should have been in PS_EQUATES
Equ MENUPOS_TYPE$ To 1
Equ MENUPOS_END$ To 2
Equ MENUPOS_ITEMNAME$ To 3
Equ MENUPOS_TEXT$ To 4
Equ MENUPOS_GREY$ To 5
Equ MENUPOS_CHECK$ To 6
Equ MENUPOS_HIDDEN$ To 7
Equ MENUPOS_ACCEL$ To 8
Equ MENUPOS_HELP_TEXT$ To 9
Equ MENUPOS_HANDLER$ To 10
Equ MENUPOS_STYLE$ To 11
* // These are used by CREATE_CONTEXT_MENU, and denote the structure of a menu item as passed in the
* // second parameter
* Menu equates
Equ MenuItem_Name$ to 1
Equ MenuItem_Pos$ to 2
Equ MenuItem_Text$ to 3
Equ MenuItem_State$ to 4
Equ MF_ByCommand$ to 0x000
Equ MF_ByPosition$ to 0x0400
Equ MF_Separator$ to 2048
Equ MenuItemTypePos$ To 1
Equ MenuItemTextPos$ To 2
Equ MenuItemNamePos$ To 3
Equ MenuItemGrayPos$ To 4
Equ MenuItemCheckPos$ To 5
Equ MenuItemStylePos$ To 6
Equ MenuItemEndFlagPos$ To 7
Equ ContextMenuSuffix$ To ".CONTEXT_MENU"
Equ ContextMenuClass$ To "FLOATING"
Equ ContextMenuType$ To "MENU"
Equ ContextMenuHeaderType$ To ".POPUP"

View File

@ -0,0 +1,3 @@
compile insert SECURITY_EQUATES
Common /Application Security/ Username%, Login%, AccessLevel%, SecurityUnused4%, SecurityUnused5%, SecurityUnused6%, SecurityUnused7%, SecurityUnused8%

View File

@ -0,0 +1,43 @@
Compile insert Service_Setup
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : Service_Setup
Description : Equates used by the Service modules.
Notes :
History : (Date, Initials, Notes)
08/13/10 dmb Original programmer.
***********************************************************************************************************************/
Declare function RetStack, Error_Services
Declare subroutine Error_Services
// Make sure any request parameters which have not been assigned are nulled.
If Assigned(Service) else Service = ''
If Assigned(Error) else Error = ''
If Assigned(Param1) else Param1 = ''
If Assigned(Param2) else Param2 = ''
If Assigned(Param3) else Param3 = ''
If Assigned(Param4) else Param4 = ''
If Assigned(Param5) else Param5 = ''
If Assigned(Param6) else Param6 = ''
If Assigned(Param7) else Param7 = ''
If Assigned(Param8) else Param8 = ''
If Assigned(Param9) else Param9 = ''
If Assigned(Param10) else Param10 = ''
If Assigned(Response) else Response = ''
// Create the service Key ID in case Memory_Services is used.
ServiceModule = RetStack()<1>
ServiceKeyID = ServiceModule : '*' : Service
// Clear any error conditions.
Error_Services('Clear')

View File

@ -0,0 +1,42 @@
Compile insert SRPMAIL_INSERTS
Declare function SRPSendMail, SRP_Send_Mail
*----------------------------------------------------
* Configuration
* field
Equ SendUsing$ to 1
Equ SMTPServerPickupDir$ to 2
Equ SMTPServerPort$ to 3
Equ SMTPServer$ to 4
Equ SMTPAuthenticate$ to 5
Equ SMTPSendUsername$ to 6
Equ SMTPSendPassword$ to 7
* SendUsing values
Equ SendUsing_Pickup$ to 1
Equ SendUsing_Port$ to 2
* SMTPServerPort values
Equ SMTPServerPortDefault$ to 25
*----------------------------------------------------
* Message
* fields
Equ SRPMail_Subject$ to 1
Equ SRPMail_From$ to 2
Equ SRPMail_To$ to 3
Equ SRPMail_Cc$ to 4
Equ SRPMail_Bcc$ to 5
Equ SRPMail_ReplyTo$ to 6
Equ SRPMail_BodyType$ to 7
Equ SRPMail_Body$ to 8
Equ SRPMail_Attachments$ to 9
Equ SRPMail_Importance$ to 10
* Importance Levels
Equ SRPMail_Importance_Low$ to 0
Equ SRPMail_Importance_Normal$ to 1
Equ SRPMail_Importance_High$ to 2

View File

@ -0,0 +1,36 @@
compile insert WEB_ACCOUNTS_EQUATES
/***********************************************************************************************************************
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
permission from SRP Computer Solutions, Inc.
Name : WEB_ACCOUNTS_EQUATES
Description : Equates used by any service that works with the WEB_ACCOUNTS database table.
Notes :
History : (Date, Initials, Notes)
10/30/18 dmb Original programmer. - [SRPFW-254]
11/01/18 dmb Add WEB_ACCOUNTS.ACCOUNT_ENABLED$. - [SRPFW-256]
11/01/18 dmb Add WEB_ACCOUNTS.INVALID_PASSWORD_ATTEMPTS$. - [SRPFW-256]
***********************************************************************************************************************/
Equ WEB_ACCOUNTS.ID$ To 0
Equ WEB_ACCOUNTS.MODIFIED_BY$ To 1
Equ WEB_ACCOUNTS.MODIFIED_DATE$ To 2
Equ WEB_ACCOUNTS.MODIFIED_TIME$ To 3
Equ WEB_ACCOUNTS.NAME$ To 4
Equ WEB_ACCOUNTS.CURRENT_PASSWORD$ To 5
Equ WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_DATE$ To 6
Equ WEB_ACCOUNTS.CURRENT_PASSWORD_CREATE_TIME$ To 7
Equ WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_DATE$ To 8
Equ WEB_ACCOUNTS.CURRENT_PASSWORD_EXPIRE_TIME$ To 9
Equ WEB_ACCOUNTS.OLD_PASSWORD$ To 10
Equ WEB_ACCOUNTS.OLD_PASSWORD_CREATE_DATE$ To 11
Equ WEB_ACCOUNTS.OLD_PASSWORD_CREATE_TIME$ To 12
Equ WEB_ACCOUNTS.OLD_PASSWORD_EXPIRE_DATE$ To 13
Equ WEB_ACCOUNTS.OLD_PASSWORD_EXPIRE_TIME$ To 14
Equ WEB_ACCOUNTS.ACCOUNT_ENABLED$ To 15
Equ WEB_ACCOUNTS.INVALID_PASSWORD_ATTEMPTS$ To 16