filemaker 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +17 -0
  5. data/.travis.yml +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +116 -0
  9. data/Rakefile +6 -0
  10. data/diagram.png +0 -0
  11. data/filemaker.gemspec +30 -0
  12. data/lib/filemaker.rb +13 -0
  13. data/lib/filemaker/api.rb +13 -0
  14. data/lib/filemaker/api/query_commands/delete.rb +16 -0
  15. data/lib/filemaker/api/query_commands/dup.rb +22 -0
  16. data/lib/filemaker/api/query_commands/edit.rb +26 -0
  17. data/lib/filemaker/api/query_commands/find.rb +46 -0
  18. data/lib/filemaker/api/query_commands/findall.rb +34 -0
  19. data/lib/filemaker/api/query_commands/findany.rb +26 -0
  20. data/lib/filemaker/api/query_commands/findquery.rb +84 -0
  21. data/lib/filemaker/api/query_commands/new.rb +21 -0
  22. data/lib/filemaker/api/query_commands/view.rb +11 -0
  23. data/lib/filemaker/configuration.rb +28 -0
  24. data/lib/filemaker/core_ext/hash.rb +32 -0
  25. data/lib/filemaker/database.rb +29 -0
  26. data/lib/filemaker/error.rb +391 -0
  27. data/lib/filemaker/layout.rb +38 -0
  28. data/lib/filemaker/metadata/field.rb +71 -0
  29. data/lib/filemaker/record.rb +64 -0
  30. data/lib/filemaker/resultset.rb +124 -0
  31. data/lib/filemaker/script.rb +9 -0
  32. data/lib/filemaker/server.rb +197 -0
  33. data/lib/filemaker/store/database_store.rb +21 -0
  34. data/lib/filemaker/store/layout_store.rb +23 -0
  35. data/lib/filemaker/store/script_store.rb +23 -0
  36. data/lib/filemaker/version.rb +3 -0
  37. data/spec/filemaker/api/query_commands/compound_find_spec.rb +69 -0
  38. data/spec/filemaker/error_spec.rb +257 -0
  39. data/spec/filemaker/layout_spec.rb +229 -0
  40. data/spec/filemaker/metadata/field_spec.rb +62 -0
  41. data/spec/filemaker/record_spec.rb +47 -0
  42. data/spec/filemaker/resultset_spec.rb +65 -0
  43. data/spec/filemaker/server_spec.rb +106 -0
  44. data/spec/filemaker/store/database_store_spec.rb +34 -0
  45. data/spec/filemaker/store/layout_store_spec.rb +31 -0
  46. data/spec/filemaker/store/script_store_spec.rb +31 -0
  47. data/spec/spec_helper.rb +84 -0
  48. data/spec/support/responses/dbnames.xml +34 -0
  49. data/spec/support/responses/employment.xml +55 -0
  50. data/spec/support/responses/jobs.xml +199 -0
  51. data/spec/support/responses/layoutnames.xml +39 -0
  52. data/spec/support/responses/portal.xml +108 -0
  53. data/spec/support/responses/scriptnames.xml +29 -0
  54. data/spec/support/xml_loader.rb +29 -0
  55. metadata +227 -0
@@ -0,0 +1,84 @@
1
+ module Filemaker
2
+ module Api
3
+ module QueryCommands
4
+ # Find records using compound find query command.
5
+ #
6
+ # query(status: 'open', title: 'web') => (q0,q1)
7
+ # query(status: %w(open closed)) => (q0);(q1)
8
+ #
9
+ def query(array_hash)
10
+ compound_find = CompoundFind.new(array_hash)
11
+
12
+ query_hash = compound_find.key_values.merge(
13
+ '-query' => compound_find.key_maps_string
14
+ )
15
+
16
+ findquery(query_hash)
17
+ end
18
+
19
+ # Raw -findquery if you want to construct your own.
20
+ def findquery(query_hash, options = {})
21
+ perform_request('-findquery', query_hash, options)
22
+ end
23
+
24
+ # Convenient compound find query builder
25
+ class CompoundFind
26
+ attr_reader :key_values, :key_maps_string
27
+
28
+ def initialize(query)
29
+ @query = query
30
+ @key_values = {}
31
+ @key_maps = []
32
+ @key_maps_string = ''
33
+ @counter = 0
34
+
35
+ become_array(@query).each do |hash|
36
+ build_key_map(build_key_values(hash))
37
+ end
38
+
39
+ translate_key_maps
40
+ end
41
+
42
+ private
43
+
44
+ def build_key_values(hash)
45
+ q_tag_array = []
46
+ omit = hash.delete('-omit')
47
+
48
+ hash.each do |key, value|
49
+ q_tag = []
50
+ become_array(value).each do |v|
51
+ @key_values["-q#{@counter}"] = key
52
+ @key_values["-q#{@counter}.value"] = v
53
+ q_tag << "q#{@counter}"
54
+ @counter += 1
55
+ end
56
+ q_tag_array << q_tag
57
+ end
58
+
59
+ (q_tag_array << '-omit') if omit
60
+ q_tag_array
61
+ end
62
+
63
+ def build_key_map(q_tag_array)
64
+ omit = q_tag_array.delete('-omit')
65
+ len = q_tag_array.length
66
+ result = q_tag_array.flatten.combination(len).select do |c|
67
+ q_tag_array.all? { |a| (a & c).size > 0 }
68
+ end.each { |c| c.unshift('-omit') if omit }
69
+ @key_maps.concat result
70
+ end
71
+
72
+ def translate_key_maps
73
+ @key_maps_string << @key_maps.map do |a|
74
+ "#{'!' if a.delete('-omit')}(#{a.join(',')})"
75
+ end.join(';')
76
+ end
77
+
78
+ def become_array(value)
79
+ value.is_a?(Array) ? value : [value]
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,21 @@
1
+ module Filemaker
2
+ module Api
3
+ module QueryCommands
4
+ # Add new record.
5
+ #
6
+ # -script
7
+ # -script.param
8
+ # -relatedsets.filter
9
+ # -relatedsets.max
10
+ #
11
+ def new(values, options = {})
12
+ valid_options(options,
13
+ :script,
14
+ :relatedsets_filter,
15
+ :relatedsets_max)
16
+
17
+ perform_request('-new', values, options)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Filemaker
2
+ module Api
3
+ module QueryCommands
4
+ # Retrieves <metadata> section of XML.
5
+ #
6
+ def view
7
+ perform_request('-view', {}, {})
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ module Filemaker
2
+ class Configuration
3
+ attr_accessor :host, :account_name, :password, :ssl, :endpoint
4
+ attr_accessor :log
5
+
6
+ def initialize
7
+ @endpoint = '/fmi/xml/fmresultset.xml'
8
+ end
9
+
10
+ def not_configurable?
11
+ host_missing? || account_name_missing? || password_missing?
12
+ end
13
+
14
+ %w(host account_name password).each do |name|
15
+ define_method "#{name}_missing?" do
16
+ (send(name.to_sym) || '').empty?
17
+ end
18
+ end
19
+
20
+ def connection_options
21
+ ssl.is_a?(Hash) ? { ssl: ssl } : {}
22
+ end
23
+
24
+ def url
25
+ (ssl.is_a?(Hash) || ssl == true) ? "https://#{host}" : "http://#{host}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ class Hash
2
+ def transform_keys
3
+ return enum_for(:transform_keys) unless block_given?
4
+ result = self.class.new
5
+ each_key do |key|
6
+ result[yield(key)] = self[key]
7
+ end
8
+ result
9
+ end
10
+
11
+ def stringify_keys
12
+ transform_keys { |key| key.to_s }
13
+ end
14
+ end
15
+
16
+ module Filemaker
17
+ class HashWithIndifferentAndCaseInsensitiveAccess < Hash
18
+ def []=(key, value)
19
+ super(convert_key(key), value)
20
+ end
21
+
22
+ def [](key)
23
+ super(convert_key(key))
24
+ end
25
+
26
+ protected
27
+
28
+ def convert_key(key)
29
+ key.to_s.downcase
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module Filemaker
2
+ class Database
3
+ # @return [String] database name
4
+ attr_reader :name
5
+
6
+ # @return [Filemaker::Server] the server
7
+ attr_reader :server
8
+
9
+ # @return [Filemaker::Store::LayoutStore] the layout store
10
+ attr_reader :layouts
11
+ alias_method :layout, :layouts
12
+ alias_method :lay, :layouts
13
+
14
+ # @return [Filemaker::Store::ScriptStore] the script store
15
+ attr_reader :scripts
16
+
17
+ def initialize(name, server)
18
+ @name = name
19
+ @server = server
20
+ @layouts = Store::LayoutStore.new(server, self)
21
+ @scripts = Store::ScriptStore.new(server, self)
22
+ end
23
+
24
+ # A very convenient way to access some layout from this database
25
+ def [](layout_name)
26
+ layouts[layout_name]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,391 @@
1
+ module Filemaker
2
+ module Error
3
+ class CommunicationError < StandardError; end
4
+ class AuthenticationError < StandardError; end
5
+ class ParameterError < StandardError; end
6
+ class CoerceError < StandardError; end
7
+
8
+ class FilemakerError < StandardError
9
+ attr_reader :code
10
+
11
+ def initialize(code, message = nil)
12
+ @code = code
13
+ super(message)
14
+ end
15
+ end
16
+
17
+ class SystemError < FilemakerError; end
18
+
19
+ class UnknownError < SystemError; end
20
+ class UserCancelledError < SystemError; end
21
+ class MemoryError < SystemError; end
22
+ class CommandNotAvailableError < SystemError; end
23
+ class CommandUnknownError < SystemError; end
24
+ class CommandInvalidError < SystemError; end
25
+ class FileReadOnlyError < SystemError; end
26
+ class OutOfMemoryError < SystemError; end
27
+ class EmptyResultError < SystemError; end
28
+ class InsufficientPrivilegesError < SystemError; end
29
+ class RequestedDataMissingError < SystemError; end
30
+
31
+ class MissingError < FilemakerError; end
32
+ class FileMissingError < MissingError; end
33
+ class RecordMissingError < MissingError; end
34
+ class FieldMissingError < MissingError; end
35
+ class ScriptMissingError < MissingError; end
36
+ class LayoutMissingError < MissingError; end
37
+ class TableMissingError < MissingError; end
38
+
39
+ class SecurityError < FilemakerError; end
40
+ class RecordAccessDeniedError < SecurityError; end
41
+ class FieldCannotBeModifiedError < SecurityError; end
42
+ class FieldAccessDeniedError < SecurityError; end
43
+
44
+ class ConcurrencyError < FilemakerError; end
45
+ class FileLockedError < ConcurrencyError; end
46
+ class RecordInUseError < ConcurrencyError; end
47
+ class TableInUseError < ConcurrencyError; end
48
+ class RecordModificationIdMismatchError < ConcurrencyError; end
49
+
50
+ class GeneralError < FilemakerError; end
51
+ class FindCriteriaEmptyError < GeneralError; end
52
+ class NoRecordsFoundError < GeneralError; end
53
+
54
+ class ValidationError < FilemakerError; end
55
+ class DateValidationError < ValidationError; end
56
+ class TimeValidationError < ValidationError; end
57
+ class NumberValidationError < ValidationError; end
58
+ class RangeValidationError < ValidationError; end
59
+ class UniquenessValidationError < ValidationError; end
60
+ class ExistingValidationError < ValidationError; end
61
+ class ValueListValidationError < ValidationError; end
62
+ class CalculationValidationError < ValidationError; end
63
+ class InvalidFindModeValueValidationError < ValidationError; end
64
+ class MaximumCharactersValidationError < ValidationError; end
65
+
66
+ class FileError < FilemakerError; end
67
+ class UnableToCreateFileError < FileError; end
68
+ class UnableToCreateTempFileError < FileError; end
69
+ class UnableToOpenFileError < FileError; end
70
+
71
+ def self.raise_error_by_code(code)
72
+ msg = error_message_by_code(code)
73
+ error_class = find_error_class_by_code(code)
74
+ raise error_class.new(code, msg)
75
+ end
76
+
77
+ def self.error_message_by_code(code)
78
+ "FileMaker Error: #{code} (#{DESCRIPTION.fetch(code.to_s) { '??' }})"
79
+ end
80
+
81
+ def self.find_error_class_by_code(code)
82
+ case code
83
+ when -1 then UnknownError
84
+ when 1..99
85
+ if code == 1; UserCancelledError
86
+ elsif code == 2; MemoryError
87
+ elsif code == 3; CommandNotAvailableError
88
+ elsif code == 4; CommandUnknownError
89
+ elsif code == 5; CommandInvalidError
90
+ elsif code == 6; FileReadOnlyError
91
+ elsif code == 7; OutOfMemoryError
92
+ elsif code == 8; EmptyResultError
93
+ elsif code == 9; InsufficientPrivilegesError
94
+ elsif code == 10; RequestedDataMissingError
95
+ else SystemError; end
96
+ when 100..199
97
+ if code == 100; FileMissingError
98
+ elsif code == 101; RecordMissingError
99
+ elsif code == 102; FieldMissingError
100
+ elsif code == 104; ScriptMissingError
101
+ elsif code == 105; LayoutMissingError
102
+ elsif code == 106; TableMissingError
103
+ else MissingError; end
104
+ when 200..299
105
+ if code == 200; RecordAccessDeniedError
106
+ elsif code == 201; FieldCannotBeModifiedError
107
+ elsif code == 202; FieldAccessDeniedError
108
+ else SecurityError; end
109
+ when 300..399
110
+ if code == 300; FileLockedError
111
+ elsif code == 301; RecordInUseError
112
+ elsif code == 302; TableInUseError
113
+ elsif code == 306; RecordModificationIdMismatchError
114
+ else ConcurrencyError; end
115
+ when 400..499
116
+ if code == 400; FindCriteriaEmptyError
117
+ elsif code == 401; NoRecordsFoundError
118
+ else; GeneralError; end
119
+ when 500..599
120
+ if code == 500; DateValidationError
121
+ elsif code == 501; TimeValidationError
122
+ elsif code == 502; NumberValidationError
123
+ elsif code == 503; RangeValidationError
124
+ elsif code == 504; UniquenessValidationError
125
+ elsif code == 505; ExistingValidationError
126
+ elsif code == 506; ValueListValidationError
127
+ elsif code == 507; CalculationValidationError
128
+ elsif code == 508; InvalidFindModeValueValidationError
129
+ elsif code == 511; MaximumCharactersValidationError
130
+ else; ValidationError; end
131
+ when 800..899
132
+ if code == 800; UnableToCreateFileError
133
+ elsif code == 801; UnableToCreateTempFileError
134
+ elsif code == 802; UnableToOpenFileError
135
+ elsif code == 804; FileReadOnlyError
136
+ else; FileError; end
137
+ else
138
+ UnknownError
139
+ end
140
+ end
141
+
142
+ DESCRIPTION = {
143
+ '-1' => 'Unknown error',
144
+ '1' => 'User cancelled action',
145
+ '2' => 'Memory error',
146
+ '3' => 'Command is unavailable (for example, wrong operating system, wrong mode, etc.)',
147
+ '4' => 'Command is unknown',
148
+ '5' => 'Command is invalid (for example, a Set Field script step does not have a calculation specified)',
149
+ '6' => 'File is read-only',
150
+ '7' => 'Running out of memory',
151
+ '8' => 'Empty result',
152
+ '9' => 'Insufficient privileges',
153
+ '10' => 'Requested data is missing',
154
+ '11' => 'Name is not valid',
155
+ '12' => 'Name already exists',
156
+ '13' => 'File or object is in use',
157
+ '14' => 'Out of range',
158
+ '15' => 'Can\'t divide by zero',
159
+ '16' => 'Operation failed, request retry (for example, a user query)',
160
+ '17' => 'Attempt to convert foreign character set to UTF-16 failed',
161
+ '18' => 'Client must provide account information to proceed',
162
+ '19' => 'String contains characters other than A-Z, a-z, 0-9 (ASCII)',
163
+ '20' => 'Command or operation cancelled by triggered script',
164
+ '21' => 'Request not supported (for example, when creating a hard link on a file system that does not support hard links)',
165
+ '100' => 'File is missing',
166
+ '101' => 'Record is missing',
167
+ '102' => 'Field is missing',
168
+ '103' => 'Relationship is missing',
169
+ '104' => 'Script is missing',
170
+ '105' => 'Layout is missing',
171
+ '106' => 'Table is missing',
172
+ '107' => 'Index is missing',
173
+ '108' => 'Value list is missing',
174
+ '109' => 'Privilege set is missing',
175
+ '110' => 'Related tables are missing',
176
+ '111' => 'Field repetition is invalid',
177
+ '112' => 'Window is missing',
178
+ '113' => 'Function is missing',
179
+ '114' => 'File reference is missing',
180
+ '115' => 'Menu set is missing',
181
+ '116' => 'Layout object is missing',
182
+ '117' => 'Data source is missing',
183
+ '118' => 'Theme is missing',
184
+ '130' => 'Files are damaged or missing and must be reinstalled',
185
+ '131' => 'Language pack files are missing (such as Starter Solutions)',
186
+ '200' => 'Record access is denied',
187
+ '201' => 'Field cannot be modified',
188
+ '202' => 'Field access is denied',
189
+ '203' => 'No records in file to print, or password doesn\'t allow print access',
190
+ '204' => 'No access to field(s) in sort order',
191
+ '205' => 'User does not have access privileges to create new records; import will overwrite existing data',
192
+ '206' => 'User does not have password change privileges, or file is not modifiable',
193
+ '207' => 'User does not have sufficient privileges to change database schema, or file is not modifiable',
194
+ '208' => 'Password does not contain enough characters',
195
+ '209' => 'New password must be different from existing one',
196
+ '210' => 'User account is inactive',
197
+ '211' => 'Password has expired',
198
+ '212' => 'Invalid user account and/or password. Please try again',
199
+ '213' => 'User account and/or password does not exist',
200
+ '214' => 'Too many login attempts',
201
+ '215' => 'Administrator privileges cannot be duplicated',
202
+ '216' => 'Guest account cannot be duplicated',
203
+ '217' => 'User does not have sufficient privileges to modify administrator account',
204
+ '218' => 'Password and verify password do not match',
205
+ '300' => 'File is locked or in use',
206
+ '301' => 'Record is in use by another user',
207
+ '302' => 'Table is in use by another user',
208
+ '303' => 'Database schema is in use by another user',
209
+ '304' => 'Layout is in use by another user',
210
+ '306' => 'Record modification ID does not match',
211
+ '307' => 'Transaction could not be locked because of a communication error with the host',
212
+ '308' => 'Theme is locked and in use by another user',
213
+ '400' => 'Find criteria are empty',
214
+ '401' => 'No records match the request',
215
+ '402' => 'Selected field is not a match field for a lookup',
216
+ '403' => 'Exceeding maximum record limit for trial version of FileMaker Pro',
217
+ '404' => 'Sort order is invalid',
218
+ '405' => 'Number of records specified exceeds number of records that can be omitted',
219
+ '406' => 'Replace/Reserialize criteria are invalid',
220
+ '407' => 'One or both match fields are missing (invalid relationship)',
221
+ '408' => 'Specified field has inappropriate data type for this operation',
222
+ '409' => 'Import order is invalid',
223
+ '410' => 'Export order is invalid',
224
+ '412' => 'Wrong version of FileMaker Pro used to recover file',
225
+ '413' => 'Specified field has inappropriate field type',
226
+ '414' => 'Layout cannot display the result',
227
+ '415' => 'One or more required related records are not available',
228
+ '416' => 'A primary key is required from the data source table',
229
+ '417' => 'Database is not a supported data source',
230
+ '418' => 'Internal failure in INSERT operation into a field',
231
+ '500' => 'Date value does not meet validation entry options',
232
+ '501' => 'Time value does not meet validation entry options',
233
+ '502' => 'Number value does not meet validation entry options',
234
+ '503' => 'Value in field is not within the range specified in validation entry options',
235
+ '504' => 'Value in field is not unique as required in validation entry options',
236
+ '505' => 'Value in field is not an existing value in the database file as required in validation entry options',
237
+ '506' => 'Value in field is not listed on the value list specified in validation entry option',
238
+ '507' => 'Value in field failed calculation test of validation entry option',
239
+ '508' => 'Invalid value entered in Find mode',
240
+ '509' => 'Field requires a valid value',
241
+ '510' => 'Related value is empty or unavailable',
242
+ '511' => 'Value in field exceeds maximum field size',
243
+ '512' => 'Record was already modified by another user',
244
+ '513' => 'No validation was specified but data cannot fit into the field',
245
+ '600' => 'Print error has occurred',
246
+ '601' => 'Combined header and footer exceed one page',
247
+ '602' => 'Body doesn\'t fit on a page for current column setup',
248
+ '603' => 'Print connection lost',
249
+ '700' => 'File is of the wrong file type for import',
250
+ '706' => 'EPSF file has no preview image',
251
+ '707' => 'Graphic translator cannot be found',
252
+ '708' => 'Can\'t import the file or need color monitor support to import file',
253
+ '709' => 'QuickTime movie import failed',
254
+ '710' => 'Unable to update QuickTime file reference because the database file is read-only',
255
+ '711' => 'Import translator cannot be found',
256
+ '714' => 'Password privileges do not allow the operation',
257
+ '715' => 'Specified Excel worksheet or named range is missing',
258
+ '716' => 'A SQL query using DELETE, INSERT, or UPDATE is not allowed for ODBC import',
259
+ '717' => 'There is not enough XML/XSL information to proceed with the import or export',
260
+ '718' => 'Error in parsing XML file (from Xerces)',
261
+ '719' => 'Error in transforming XML using XSL (from Xalan)',
262
+ '720' => 'Error when exporting; intended format does not support repeating fields',
263
+ '721' => 'Unknown error occurred in the parser or the transformer',
264
+ '722' => 'Cannot import data into a file that has no fields',
265
+ '723' => 'You do not have permission to add records to or modify records in the target table',
266
+ '724' => 'You do not have permission to add records to the target table',
267
+ '725' => 'You do not have permission to modify records in the target table',
268
+ '726' => 'There are more records in the import file than in the target table. Not all records were imported',
269
+ '727' => 'There are more records in the target table than in the import file. Not all records were updated',
270
+ '729' => 'Errors occurred during import. Records could not be imported',
271
+ '730' => 'Unsupported Excel version (convert file to Excel 2007/2008 format or a later supported version and try again)',
272
+ '731' => 'File you are importing from contains no data',
273
+ '732' => 'This file cannot be inserted because it contains other files',
274
+ '733' => 'A table cannot be imported into itself',
275
+ '734' => 'This file type cannot be displayed as a picture',
276
+ '735' => 'This file type cannot be displayed as a picture. It will be inserted and displayed as a file',
277
+ '736' => 'There is too much data to be exported to this format. It will be truncated.',
278
+ '737' => 'Bento table you are importing is missing',
279
+ '738' => 'The theme you are importing already exists',
280
+ '800' => 'Unable to create file on disk',
281
+ '801' => 'Unable to create temporary file on System disk',
282
+ '802' => 'Unable to open file',
283
+ '803' => 'File is single user or host cannot be found',
284
+ '804' => 'File cannot be opened as read-only in its current state',
285
+ '805' => 'File is damaged; use Recover command',
286
+ '806' => 'File cannot be opened with this version of FileMaker Pro',
287
+ '807' => 'File is not a FileMaker Pro file or is severely damaged',
288
+ '808' => 'Cannot open file because access privileges are damaged',
289
+ '809' => 'Disk/volume is full',
290
+ '810' => 'Disk/volume is locked',
291
+ '811' => 'Temporary file cannot be opened as FileMaker Pro file',
292
+ '812' => 'Exceeded host\'s capacity',
293
+ '813' => 'Record Synchronization error on network',
294
+ '814' => 'File(s) cannot be opened because maximum number is open',
295
+ '815' => 'Couldn\'t open lookup file',
296
+ '816' => 'Unable to convert file',
297
+ '817' => 'Unable to open file because it does not belong to this solution',
298
+ '819' => 'Cannot save a local copy of a remote file',
299
+ '820' => 'File is in the process of being closed',
300
+ '821' => 'Host forced a disconnect',
301
+ '822' => 'FMI files not found; reinstall missing files',
302
+ '823' => 'Cannot set file to single-user, guests are connected',
303
+ '824' => 'File is damaged or not a FileMaker file',
304
+ '825' => 'File is not authorized to reference the protected file',
305
+ '826' => 'File path specified is not a valid file path',
306
+ '850' => 'Path is not valid for the operating system',
307
+ '851' => 'Cannot delete an external file from disk',
308
+ '852' => 'Cannot write a file to the external storage',
309
+ '853' => 'One or more containers failed to transfer',
310
+ '900' => 'General spelling engine error',
311
+ '901' => 'Main spelling dictionary not installed',
312
+ '902' => 'Could not launch the Help system',
313
+ '903' => 'Command cannot be used in a shared file',
314
+ '905' => 'No active field selected; command can only be used if there is an active field',
315
+ '906' => 'Current file is not shared; command can be used only if the file is shared',
316
+ '920' => 'Can\'t initialize the spelling engine',
317
+ '921' => 'User dictionary cannot be loaded for editing',
318
+ '922' => 'User dictionary cannot be found',
319
+ '923' => 'User dictionary is read-only',
320
+ '951' => 'An unexpected error occurred',
321
+ '954' => 'Unsupported XML grammar',
322
+ '955' => 'No database name',
323
+ '956' => 'Maximum number of database sessions exceeded',
324
+ '957' => 'Conflicting commands',
325
+ '958' => 'Parameter missing in query',
326
+ '959' => 'Custom Web Publishing technology is disabled',
327
+ '960' => 'Parameter is invalid',
328
+ '1200' => 'Generic calculation error',
329
+ '1201' => 'Too few parameters in the function',
330
+ '1202' => 'Too many parameters in the function',
331
+ '1203' => 'Unexpected end of calculation',
332
+ '1204' => 'Number, text constant, field name or "(" expected',
333
+ '1205' => 'Comment is not terminated with "*/"',
334
+ '1206' => 'Text constant must end with a quotation mark',
335
+ '1207' => 'Unbalanced parenthesis',
336
+ '1208' => 'Operator missing, function not found or "(" not expected',
337
+ '1209' => 'Name (such as field name or layout name) is missing',
338
+ '1210' => 'Plug-in function has already been registered',
339
+ '1211' => 'List usage is not allowed in this function',
340
+ '1212' => 'An operator (for example, +, -, *) is expected here',
341
+ '1213' => 'This variable has already been defined in the Let function',
342
+ '1214' => 'AVERAGE, COUNT, EXTEND, GETREPETITION, MAX, MIN, NPV, STDEV, SUM and GETSUMMARY: expression found where a field alone is needed',
343
+ '1215' => 'This parameter is an invalid Get function parameter',
344
+ '1216' => 'Only Summary fields allowed as first argument in GETSUMMARY',
345
+ '1217' => 'Break field is invalid',
346
+ '1218' => 'Cannot evaluate the number',
347
+ '1219' => 'A field cannot be used in its own formula',
348
+ '1220' => 'Field type must be normal or calculated',
349
+ '1221' => 'Data type must be number, date, time, or timestamp',
350
+ '1222' => 'Calculation cannot be stored',
351
+ '1223' => 'Function referred to is not yet implemented',
352
+ '1224' => 'Function referred to does not exist',
353
+ '1225' => 'Function referred to is not supported in this context',
354
+ '1300' => 'The specified name can\'t be used',
355
+ '1301' => 'One of the parameters of the function being imported or pasted has the same name as a function already in the file',
356
+ '1400' => 'ODBC client driver initialization failed; make sure the ODBC client drivers are properly installed',
357
+ '1401' => 'Failed to allocate environment (ODBC)',
358
+ '1402' => 'Failed to free environment (ODBC)',
359
+ '1403' => 'Failed to disconnect (ODBC)',
360
+ '1404' => 'Failed to allocate connection (ODBC)',
361
+ '1405' => 'Failed to free connection (ODBC)',
362
+ '1406' => 'Failed check for SQL API (ODBC)',
363
+ '1407' => 'Failed to allocate statement (ODBC)',
364
+ '1408' => 'Extended error (ODBC)',
365
+ '1409' => 'Extended error (ODBC)',
366
+ '1410' => 'Extended error (ODBC)',
367
+ '1411' => 'Extended error (ODBC)',
368
+ '1412' => 'Extended error (ODBC)',
369
+ '1413' => 'Extended error (ODBC)',
370
+ '1414' => 'SQL statement is too long',
371
+ '1450' => 'Action requires PHP privilege extension',
372
+ '1451' => 'Action requires that current file be remote',
373
+ '1501' => 'SMTP authentication failed',
374
+ '1502' => 'Connection refused by SMTP server',
375
+ '1503' => 'Error with SSL',
376
+ '1504' => 'SMTP server requires the connection to be encrypted',
377
+ '1505' => 'Specified authentication is not supported by SMTP server',
378
+ '1506' => 'Email message(s) could not be sent successfully',
379
+ '1507' => 'Unable to log in to the SMTP server',
380
+ '1550' => 'Cannot load the plug-in or the plug-in is not a valid plug-in',
381
+ '1551' => 'Cannot install the plug-in. Cannot delete an existing plug-in or cannot write to the folder or disk',
382
+ '1626' => 'Protocol is not supported',
383
+ '1627' => 'Authentication failed',
384
+ '1628' => 'There was an error with SSL',
385
+ '1629' => 'Connection timed out; the timeout value is 60 seconds',
386
+ '1630' => 'URL format is incorrect',
387
+ '1631' => 'Connection failed',
388
+ '8003' => 'Lock conflict with database users or other error'
389
+ }
390
+ end
391
+ end