1/*
2 *  IODBCadm_DSNmanageController.m
3 *
4 *  $Id$
5 *
6 *  The iODBC driver manager.
7 *
8 *  Copyright (C) 1996-2021 OpenLink Software <iodbc@openlinksw.com>
9 *  All Rights Reserved.
10 *
11 *  This software is released under the terms of either of the following
12 *  licenses:
13 *
14 *      - GNU Library General Public License (see LICENSE.LGPL)
15 *      - The BSD License (see LICENSE.BSD).
16 *
17 *  Note that the only valid version of the LGPL license as far as this
18 *  project is concerned is the original GNU Library General Public License
19 *  Version 2, dated June 1991.
20 *
21 *  While not mandated by the BSD license, any patches you make to the
22 *  iODBC source code may be contributed back into the iODBC project
23 *  at your discretion. Contributions will benefit the Open Source and
24 *  Data Access community as a whole. Submissions may be made at:
25 *
26 *      http://www.iodbc.org
27 *
28 *
29 *  GNU Library Generic Public License Version 2
30 *  ============================================
31 *  This library is free software; you can redistribute it and/or
32 *  modify it under the terms of the GNU Library General Public
33 *  License as published by the Free Software Foundation; only
34 *  Version 2 of the License dated June 1991.
35 *
36 *  This library is distributed in the hope that it will be useful,
37 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
38 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39 *  Library General Public License for more details.
40 *
41 *  You should have received a copy of the GNU Library General Public
42 *  License along with this library; if not, write to the Free
43 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
44 *
45 *
46 *  The BSD License
47 *  ===============
48 *  Redistribution and use in source and binary forms, with or without
49 *  modification, are permitted provided that the following conditions
50 *  are met:
51 *
52 *  1. Redistributions of source code must retain the above copyright
53 *     notice, this list of conditions and the following disclaimer.
54 *  2. Redistributions in binary form must reproduce the above copyright
55 *     notice, this list of conditions and the following disclaimer in
56 *     the documentation and/or other materials provided with the
57 *     distribution.
58 *  3. Neither the name of OpenLink Software Inc. nor the names of its
59 *     contributors may be used to endorse or promote products derived
60 *     from this software without specific prior written permission.
61 *
62 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
63 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
64 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
65 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
66 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
67 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
68 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
69 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
70 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
71 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
72 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 */
74
75
76#import "IODBCadm_DSNmanageController.h"
77#import "utils.h"
78#import "Helpers.h"
79#import "IODBCadm_DriverChooseDSNController.h"
80#import "IODBCadm_PoolConfigController.h"
81#import "IODBCadm_DrvRemoveController.h"
82#import "IODBCadm_DrvConfigController.h"
83
84
85
86void create_administrator (HWND hwnd)
87{
88    @autoreleasepool {
89
90        NSApplication *app = [NSApplication sharedApplication];
91
92        IODBCadm_DSNmanageController *dlg = [[IODBCadm_DSNmanageController alloc] init];
93
94        [app runModalForWindow:dlg.window];
95
96        [dlg.window orderOut:dlg.window];
97        [dlg release];
98    }
99}
100
101
102static LPWSTR create_driversetupw (LPCWSTR driver, LPCWSTR attrs, BOOL add, BOOL user)
103{
104    wchar_t *connstr = NULL;
105
106    IODBCadm_DrvConfigController *dlg = [[IODBCadm_DrvConfigController alloc] initWithAttrs:attrs];
107    dlg.drv_name = conv_wchar_to_NSString(driver);
108    dlg.add = add;
109
110    NSInteger rc = [NSApp runModalForWindow:dlg.window];
111    if (rc == 1) {
112        int i = 0, size = 0;
113        wchar_t *cour, *prov;
114        int STRCONN_NB_TOKENS = 3;
115
116        size += (dlg.drv_name!=nil?dlg.drv_name.length:0) + 1;
117        size += (dlg.drv_file!=nil?dlg.drv_file.length:0) + wcslen(L"Driver=") +1;
118        size += (dlg.setup_file!=nil?dlg.setup_file.length:0) + wcslen(L"Setup=") +1;
119
120        size += wcslen(dlg.rb_sysuser.selectedColumn==0?L"USR" : L"SYS") + 1;
121        /* Malloc it */
122        if ((connstr = (wchar_t *) malloc (++size * sizeof(wchar_t))))
123        {
124            wcscpy(connstr, (dlg.rb_sysuser.selectedColumn==0? L"USR" : L"SYS"));
125
126            for (cour = connstr + 4; i < STRCONN_NB_TOKENS ; i++)
127            {
128                switch (i)
129                {
130                    case 0:
131                        prov = conv_NSString_to_wchar(dlg.drv_name);
132                        if(prov)
133                        {
134                            wcscpy(cour, prov);
135                            free(prov);
136                        }
137                        break;
138                    case 1:
139                        prov = conv_NSString_to_wchar(dlg.drv_file);
140                        if(prov)
141                        {
142                            wcscpy(cour, L"Driver=");
143                            wcscat(cour, prov);
144                            free(prov);
145                        }
146                        break;
147                    case 2:
148                        prov = conv_NSString_to_wchar(dlg.setup_file);
149                        if(prov)
150                        {
151                            wcscpy(cour, L"Setup=");
152                            wcscat(cour, prov);
153                            free(prov);
154                        }
155                        break;
156                };
157
158                cour += (wcslen (cour) + 1);
159            }
160
161            for (i = 0; i < dlg.Attrs_list.count; i++)
162            {
163                wchar_t *val,*key;
164                NSDictionary *row = [dlg.Attrs_list objectAtIndex:i];
165                NSString *nskey = (NSString*)[row valueForKey:@"key"];
166                if ([nskey isEqualToString:@"..."] || nskey.length==0)
167                    continue;
168                key = conv_NSString_to_wchar(nskey);
169                val = conv_NSString_to_wchar((NSString*)[row valueForKey:@"val"]);
170                cour = connstr;
171                connstr = (wchar_t*) malloc ((size + wcslen(key) + wcslen(val) + 2) * sizeof(wchar_t));
172                if (connstr)
173                {
174                    memcpy (connstr, cour, size*sizeof(wchar_t));
175                    if (key) {
176                        wcscpy(connstr + size - 1, key);
177                        wcscat(connstr + size - 1, L"=");
178                        if (val)
179                            wcscat(connstr + size - 1, val);
180                    }
181                    free (cour);
182                    size += wcslen(key) + wcslen(val) + 2;
183                }
184                else
185                    connstr = cour;
186
187                if (key!=NULL) free(key);
188                if (val!=NULL) free(val);
189            }
190
191            connstr[size - 1] = '\0';
192        }
193    }
194
195    [dlg.window orderOut:dlg.window];
196    [dlg release];
197
198    return connstr;
199}
200
201
202
203@interface IODBCadm_DSNmanageController ()
204
205@end
206
207@implementation IODBCadm_DSNmanageController
208@synthesize fld_CustomTrace = _fld_CustomTrace;
209@synthesize fld_LogFilePath = _fld_LogFilePath;
210@synthesize rb_WhenToTrace = _rb_WhenToTrace;
211@synthesize rb_TraceWide = _rb_TraceWide;
212@synthesize fld_RetryWaitTime = _fld_RetryWaitTime;
213@synthesize pool_tableView = _pool_tableView;
214@synthesize rb_PerfMon = _rb_PerfMon;
215@synthesize popup_dir_btn = _popup_dir_btn;
216@synthesize fdsn_tableView = _fdsn_tableView;
217@synthesize tab_view = _tab_view;
218@synthesize FileDSN_ArrController = _FileDSN_ArrController;
219@synthesize SysDSN_ArrController = _SysDSN_ArrController;
220@synthesize UserDSN_ArrController = _UserDSN_ArrController;
221@synthesize Drv_ArrController = _Drv_ArrController;
222@synthesize Pool_ArrController = _Pool_ArrController;
223@synthesize About_ArrController = _About_ArrController;
224@synthesize FileDSN_list=_FileDSN_list;
225@synthesize cur_dir=_cur_dir;
226
227- (id)init
228{
229    char tmp[1024] = {""};
230
231    self = [super initWithWindowNibName:@"IODBCadm_DSNmanageController"];
232    if (self) {
233        self.FileDSN_list = [NSMutableArray arrayWithCapacity:16];
234
235        SQLSetConfigMode (ODBC_BOTH_DSN);
236        if (!SQLGetPrivateProfileString("ODBC", "FileDSNPath", "", tmp, sizeof(tmp), "odbcinst.ini"))
237          self.cur_dir = get_user_documents_dir();
238        else
239          self.cur_dir = conv_char_to_NSString(tmp);
240    }
241    _tracing_changed = FALSE;
242    _pool_changed = FALSE;
243    _drivers_loaded = FALSE;
244    return self;
245}
246
247- (void)dealloc
248{
249    [_FileDSN_list release];
250    [_cur_dir release];
251	[super dealloc];
252}
253
254
255- (id)initWithWindow:(NSWindow *)window
256{
257    self = [super initWithWindow:window];
258    if (self) {
259        // Initialization code here.
260    }
261    return self;
262}
263
264- (void)windowDidLoad
265{
266    void *ptr;
267    [super windowDidLoad];
268    _dialogCode = 0;
269
270    [[self window] center];  // Center the window.
271    self.window.title =
272#if defined (__x86_64__)
273	@"iODBC Data Source Administrator (Intel 64bit)";
274#elif defined (__aarch64__)
275	@"iODBC Data Source Administrator (Apple Silicon)";
276#elif defined (__i386__)
277	@"iODBC Data Source Administrator (Intel 32bit)";
278#else
279	@"iODBC Data Source Administrator";
280#endif
281    addDSNs_to_list(FALSE, _UserDSN_ArrController);
282    addDSNs_to_list(TRUE, _SysDSN_ArrController);
283    [_fdsn_tableView setDoubleAction:@selector(call_FDSN_DoubleClick)];
284    addPools_to_list(_Pool_ArrController);
285    [_pool_tableView setDoubleAction:@selector(call_Pool_DoubleClick)];
286    addComponents_to_list(_About_ArrController);
287}
288
289- (void)windowWillClose:(NSNotification*)notification
290{
291    [NSApp stopModalWithCode:_dialogCode];
292}
293
294- (void) call_FDSN_DoubleClick
295{
296    NSInteger row = _fdsn_tableView.clickedRow;
297    NSDictionary *dict = [_FileDSN_list objectAtIndex:row];
298    NSNumber *isdir = [dict valueForKey:@"isdir"];
299    if (isdir.boolValue==TRUE){
300        NSString *cliked_dir = [dict valueForKey:@"name"];
301        NSString *new_path = [NSString stringWithFormat:@"%@/%@", _cur_dir, cliked_dir];
302        self.cur_dir = new_path;
303        wchar_t *path = conv_NSString_to_wchar(_cur_dir);
304        addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
305        fill_dir_menu(path, _popup_dir_btn);
306        if (path) free(path);
307    } else {
308        [self call_FileDSN_Config:self];
309    }
310}
311
312
313- (void) call_Pool_DoubleClick
314{
315    NSArray *sarr = [_Pool_ArrController selectedObjects];
316    if (sarr.count>0) {
317        NSDictionary *dct = [sarr objectAtIndex:0];
318        NSString *drv = [dct valueForKey:@"drv"];
319        NSString *tm = [dct valueForKey:@"timeout"];
320        NSString *qry = [dct valueForKey:@"query"];
321
322        IODBCadm_PoolConfigController *dlg = [[IODBCadm_PoolConfigController alloc] initWithTitle:drv Timeout:tm Query:qry];
323
324        NSInteger rc = [NSApp runModalForWindow:dlg.window];
325        if (rc == 1) {
326            UWORD configMode;
327            tm = [NSString stringWithFormat:@"CPTimeout=%@", dlg.ptimeout ? dlg.ptimeout :@""];
328            qry = [NSString stringWithFormat:@"CPProbe=%@", dlg.pquery ? dlg.pquery : @""];
329
330            wchar_t *wtimeout = conv_NSString_to_wchar(tm);
331            wchar_t *wquery   = conv_NSString_to_wchar(qry);
332            wchar_t *wdrv     = conv_NSString_to_wchar(drv);
333
334            SQLGetConfigMode(&configMode);
335            SQLSetConfigMode(ODBC_SYSTEM_DSN);
336            if (wdrv) {
337                if (wtimeout) {
338                    SQLSetConfigMode(ODBC_SYSTEM_DSN);
339                    if (!SQLConfigDriverW ((void*)1L, ODBC_CONFIG_DRIVER,
340                                           wdrv, wtimeout, NULL, 0, NULL))
341                        _iodbcdm_errorboxw ((void*)1L, wdrv,
342                                            L"An error occurred when trying to set the connection pooling time-out ");
343                    free(wtimeout);
344                }
345                if (wquery) {
346                    SQLSetConfigMode(ODBC_SYSTEM_DSN);
347                    if (!SQLConfigDriverW ((void*)1L, ODBC_CONFIG_DRIVER,
348                                           wdrv, wquery, NULL, 0, NULL))
349                        _iodbcdm_errorboxw ((void*)1L, wdrv,
350                                            L"An error occurred when trying to set the connection probe query ");
351
352                }
353                free(wdrv);
354            }
355
356            addPools_to_list(_Pool_ArrController);
357        }
358
359        [dlg.window orderOut:dlg.window];
360        [dlg release];
361        [self.window makeKeyAndOrderFront:self.window];
362    }
363}
364
365
366/** NSTabViewDelegate **/
367- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem
368{
369    char tmp[4096];
370    NSString *identifier = [tabViewItem identifier];
371
372    if ([identifier isEqualToString:@"userdsn"]){
373        addDSNs_to_list(FALSE, _UserDSN_ArrController);
374    }
375    else if ([identifier isEqualToString:@"sysdsn"]){
376        addDSNs_to_list(TRUE, _SysDSN_ArrController);
377    }
378    else if ([identifier isEqualToString:@"filedsn"]){
379        wchar_t *cur_path = conv_NSString_to_wchar(_cur_dir);
380        addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
381        fill_dir_menu(cur_path, _popup_dir_btn);
382        if (cur_path) free(cur_path);
383    }
384    else if ([identifier isEqualToString:@"drivers"]){
385        if (!_drivers_loaded) {
386            addDrivers_to_list(_Drv_ArrController);
387            _drivers_loaded = TRUE;
388        }
389    }
390    else if ([identifier isEqualToString:@"pool"]){
391        if (!_pool_changed)
392        {
393            BOOL perfmon = FALSE;
394            /* Get the connection pooling options */
395            SQLGetPrivateProfileString ("ODBC Connection Pooling", "Perfmon",
396                                        "", (char *)tmp, sizeof (tmp), "odbcinst.ini");
397            if (!strcasecmp (tmp, "1") || !strcasecmp (tmp, "On"))
398                perfmon = TRUE;
399            SQLGetPrivateProfileString ("ODBC Connection Pooling", "Retry Wait",
400                                        "", tmp, sizeof (tmp), "odbcinst.ini");
401            if (perfmon)
402                [_rb_PerfMon selectCellAtRow:0 column:0];
403            else
404                [_rb_PerfMon selectCellAtRow:1 column:0];
405
406            _fld_RetryWaitTime.stringValue = conv_char_to_NSString(tmp);
407
408            _pool_changed = TRUE;
409        }
410        addPools_to_list(_Pool_ArrController);
411    }
412    else if ([identifier isEqualToString:@"trace"]){
413        wchar_t tokenstr[4096] = { L'\0' }, tokenstr1[4096] = { L'\0' };
414        BOOL trace = FALSE;
415        BOOL traceauto = FALSE;
416
417        if (!_tracing_changed)
418        {
419            int mode = ODBC_SYSTEM_DSN;
420
421            /* Get the traces options */
422            SQLSetConfigMode (mode);
423            SQLGetPrivateProfileStringW (L"ODBC", L"TraceFile", L"", tokenstr,
424                                         sizeof (tokenstr) / sizeof(wchar_t), NULL);
425            if (tokenstr[0] != L'\0')
426            {
427                /* All users wide */
428                [_rb_TraceWide selectCellAtRow:1 column:0];
429            }
430            else
431            {
432                /* Only for current user */
433                mode = ODBC_USER_DSN;
434                SQLSetConfigMode (mode);
435                [_rb_TraceWide selectCellAtRow:0 column:0];
436            }
437
438            SQLSetConfigMode (mode);
439            SQLGetPrivateProfileString ("ODBC", "Trace", "", tmp, sizeof (tmp), NULL);
440            if (!strcasecmp (tmp, "1") || !strcasecmp (tmp, "On"))
441                trace = TRUE;
442
443            SQLSetConfigMode (mode);
444            SQLGetPrivateProfileString ("ODBC", "TraceAutoStop", "", (char*)tokenstr,
445                                        sizeof (tokenstr), NULL);
446            if (!strcasecmp ((char*)tokenstr, "1") || !strcasecmp ((char*)tokenstr, "On"))
447                traceauto = TRUE;
448
449            SQLSetConfigMode (mode);
450            SQLGetPrivateProfileStringW (L"ODBC", L"TraceFile", L"", tokenstr,
451                                         sizeof (tokenstr) / sizeof(wchar_t), NULL);
452
453            SQLSetConfigMode (mode);
454            SQLGetPrivateProfileStringW (L"ODBC", L"TraceDLL", L"", tokenstr1,
455                                         sizeof (tokenstr1) / sizeof(wchar_t), NULL);
456            /* Set the widgets */
457            if (trace)
458            {
459                if (!traceauto)
460                    [_rb_WhenToTrace selectCellAtRow:1 column:0];
461                else
462                    [_rb_WhenToTrace selectCellAtRow:2 column:0];
463            }
464            else
465                [_rb_WhenToTrace selectCellAtRow:0 column:0];
466
467            _fld_LogFilePath.stringValue = tokenstr[0] == L'\0'
468                                            ? [NSString stringWithFormat:@"%@/sql.log", NSHomeDirectory()]
469                                            : conv_wchar_to_NSString(tokenstr);
470
471            _fld_CustomTrace.stringValue = conv_wchar_to_NSString(tokenstr1);
472            _tracing_changed = TRUE;
473        }
474
475
476    }
477    else if ([identifier isEqualToString:@"about"]){
478        addComponents_to_list(_About_ArrController);
479    }
480}
481
482
483
484/** NSTableViewDelegate **/
485- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
486    // Group our "model" object, which is a dictionary
487    if (tableView == _fdsn_tableView) {
488        NSDictionary *dict = [_FileDSN_list objectAtIndex:row];
489        NSString *identifier = [tableColumn identifier];
490        NSTableCellView *cellView = [tableView makeViewWithIdentifier:identifier owner:self];
491        // Then setup properties on the cellView based on the column
492        cellView.textField.stringValue = [dict objectForKey:@"name"];
493        cellView.imageView.objectValue = [dict objectForKey:@"icon"];
494        return cellView;
495    }
496    return nil;
497}
498
499
500- (IBAction)call_Ok:(id)sender {
501    _dialogCode = 1;
502    if (_tracing_changed)
503        [self call_Trace_Apply:nil];
504    if (_pool_changed) {
505        UWORD configMode;
506        char *tmp = NULL;
507
508        SQLGetConfigMode(&configMode);
509        /* Write keywords for tracing in the ini file */
510        SQLSetConfigMode(ODBC_SYSTEM_DSN);
511        SQLWritePrivateProfileString ("ODBC Connection Pooling", "PerfMon",
512                                      _rb_PerfMon.selectedRow == 0 ? "1" : "0", "odbcinst.ini");
513
514        tmp = conv_NSString_to_char(_fld_RetryWaitTime.stringValue);
515        if (tmp) {
516            SQLSetConfigMode(ODBC_SYSTEM_DSN);
517            SQLWritePrivateProfileString ("ODBC Connection Pooling",
518                                          "Retry Wait", tmp, "odbcinst.ini");
519            free(tmp);
520        }
521        SQLSetConfigMode(configMode);
522    }
523    [self.window close];
524}
525
526- (IBAction)call_Cancel:(id)sender {
527    _dialogCode = 0;
528    [self.window close];
529}
530
531
532
533- (IBAction)call_UserDSN_Add:(id)sender {
534    wchar_t drv[1024] = { L'\0' };
535    int sqlstat;
536
537    SQLSetConfigMode (ODBC_USER_DSN);
538    /* Try first to get the driver name */
539    if (_iodbcdm_drvchoose_dialboxw ((void*)1L, drv, sizeof (drv) / sizeof(wchar_t), &sqlstat) == SQL_SUCCESS)
540    {
541        SQLSetConfigMode (ODBC_USER_DSN);
542        if (!SQLConfigDataSourceW ((void*)1L, ODBC_ADD_DSN, drv + WCSLEN (L"DRIVER="), L"\0\0"))
543        {
544            _iodbcdm_errorboxw ((void*)1L, NULL, L"An error occurred when trying to add the DSN : ");
545            goto done;
546        }
547
548        addDSNs_to_list(FALSE, _UserDSN_ArrController);
549    }
550done:
551    [self.window makeKeyAndOrderFront:self.window];
552    return;
553}
554
555- (IBAction)call_UserDSN_Remove:(id)sender {
556    NSArray *item = [_UserDSN_ArrController selectedObjects];
557    if (item!=nil && item.count>0){
558        NSDictionary *dict = [item objectAtIndex:0];
559        BOOL rc = remove_dsn(FALSE, [dict valueForKey:@"name"], [dict valueForKey:@"drv"]);
560        if (rc)
561            addDSNs_to_list(FALSE, _UserDSN_ArrController);
562        [self.window makeKeyAndOrderFront:self.window];
563    }
564}
565
566- (IBAction)call_UserDSN_Config:(id)sender {
567    NSArray *item = [_UserDSN_ArrController selectedObjects];
568    if (item!=nil && item.count>0){
569        NSDictionary *dict = [item objectAtIndex:0];
570        BOOL rc = configure_dsn(FALSE, [dict valueForKey:@"name"], [dict valueForKey:@"drv"]);
571        if (rc)
572            addDSNs_to_list(FALSE, _UserDSN_ArrController);
573        [self.window makeKeyAndOrderFront:self.window];
574    }
575}
576
577
578- (IBAction)call_UserDSN_Test:(id)sender {
579    NSArray *item = [_UserDSN_ArrController selectedObjects];
580    if (item!=nil && item.count>0){
581        NSDictionary *dict = [item objectAtIndex:0];
582        test_dsn(FALSE, [dict valueForKey:@"name"], [dict valueForKey:@"drv"]);
583        [self.window makeKeyAndOrderFront:self.window];
584    }
585}
586
587
588- (IBAction)call_SysDSN_Add:(id)sender {
589    wchar_t drv[1024] = { L'\0' };
590    int sqlstat;
591
592    SQLSetConfigMode (ODBC_USER_DSN);
593    /* Try first to get the driver name */
594    if (_iodbcdm_drvchoose_dialboxw ((void*)1L, drv, sizeof (drv) / sizeof(wchar_t), &sqlstat) == SQL_SUCCESS)
595    {
596        SQLSetConfigMode (ODBC_USER_DSN);
597        if (!SQLConfigDataSourceW ((void*)1L, ODBC_ADD_SYS_DSN, drv + WCSLEN (L"DRIVER="), L"\0\0"))
598        {
599            _iodbcdm_errorboxw ((void*)1L, NULL, L"An error occurred when trying to add the DSN : ");
600            goto done;
601        }
602
603        addDSNs_to_list(TRUE, _SysDSN_ArrController);
604    }
605done:
606    [self.window makeKeyAndOrderFront:self.window];
607    return;
608}
609
610- (IBAction)call_SysDSN_Remove:(id)sender {
611    NSArray *item = [_SysDSN_ArrController selectedObjects];
612    if (item!=nil && item.count>0){
613        NSDictionary *dict = [item objectAtIndex:0];
614        BOOL rc = remove_dsn(TRUE, [dict valueForKey:@"name"], [dict valueForKey:@"drv"]);
615        if (rc)
616            addDSNs_to_list(TRUE, _SysDSN_ArrController);
617        [self.window makeKeyAndOrderFront:self.window];
618    }
619}
620
621- (IBAction)call_SysDSN_Config:(id)sender {
622    NSArray *item = [_SysDSN_ArrController selectedObjects];
623    if (item!=nil && item.count>0){
624        NSDictionary *dict = [item objectAtIndex:0];
625        BOOL rc = configure_dsn(TRUE, [dict valueForKey:@"name"], [dict valueForKey:@"drv"]);
626        if (rc)
627            addDSNs_to_list(TRUE, _SysDSN_ArrController);
628        [self.window makeKeyAndOrderFront:self.window];
629    }
630}
631
632- (IBAction)call_SysDSN_Test:(id)sender {
633    NSArray *item = [_SysDSN_ArrController selectedObjects];
634    if (item!=nil && item.count>0){
635        NSDictionary *dict = [item objectAtIndex:0];
636        test_dsn(TRUE, [dict valueForKey:@"name"], [dict valueForKey:@"drv"]);
637        [self.window makeKeyAndOrderFront:self.window];
638    }
639}
640
641
642- (IBAction)call_FileDSN_Dir_Browse:(id)sender {
643    NSOpenPanel *panel = [NSOpenPanel openPanel];
644
645    [panel setTitle:@"Choose your File DSN directory ..."];
646    if (_cur_dir.length>0)
647        [panel setDirectoryURL:[NSURL fileURLWithPath:_cur_dir isDirectory:TRUE]];
648    panel.allowsMultipleSelection = FALSE;
649    panel.canChooseDirectories = TRUE;
650    panel.canChooseFiles = FALSE;
651    panel.canCreateDirectories = TRUE;
652
653    NSInteger rc = [panel runModal];
654    if (rc==NSFileHandlingPanelOKButton) {
655        self.cur_dir = ((NSURL*)[panel.URLs objectAtIndex:0]).path;
656        wchar_t *path = conv_NSString_to_wchar(_cur_dir);
657        addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
658        fill_dir_menu(path, _popup_dir_btn);
659        if (path) free(path);
660    }
661    [self.window makeKeyAndOrderFront:self.window];
662}
663
664
665- (IBAction)call_Dir_PopupBtn:(id)sender {
666    self.cur_dir = _popup_dir_btn.titleOfSelectedItem;
667    wchar_t *path = conv_NSString_to_wchar(_cur_dir);
668    addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
669    fill_dir_menu(path, _popup_dir_btn);
670    if (path) free(path);
671}
672
673- (IBAction)call_FileDSN_Add:(id)sender {
674    BOOL rc = add_file_dsn(_cur_dir);
675    if (rc) {
676        wchar_t *cur_path = conv_NSString_to_wchar(_cur_dir);
677        addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
678        fill_dir_menu(cur_path, _popup_dir_btn);
679        if (cur_path) free(cur_path);
680    }
681    [self.window makeKeyAndOrderFront:self.window];
682}
683
684- (IBAction)call_FileDSN_Remove:(id)sender {
685    NSArray *item = [_FileDSN_ArrController selectedObjects];
686    if (item!=nil && item.count>0){
687        NSDictionary *dict = [item objectAtIndex:0];
688        NSNumber *isdir = [dict valueForKey:@"isdir"];
689        if (isdir.boolValue==FALSE){
690            BOOL rc = remove_file_dsn(_cur_dir, [dict valueForKey:@"name"]);
691            if (rc){
692                wchar_t *cur_path = conv_NSString_to_wchar(_cur_dir);
693                addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
694                fill_dir_menu(cur_path, _popup_dir_btn);
695                if (cur_path) free(cur_path);
696            }
697        }
698        [self.window makeKeyAndOrderFront:self.window];
699    }
700}
701
702- (IBAction)call_FileDSN_Config:(id)sender {
703    NSArray *item = [_FileDSN_ArrController selectedObjects];
704    if (item!=nil && item.count>0){
705        NSDictionary *dict = [item objectAtIndex:0];
706        NSNumber *isdir = [dict valueForKey:@"isdir"];
707        if (isdir.boolValue==FALSE){
708            configure_file_dsn(_cur_dir, [dict valueForKey:@"name"]);
709            char *cur_path = conv_NSString_to_char(_cur_dir);
710            addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
711            if (cur_path) free(cur_path);
712
713        } else {
714
715            self.cur_dir = [NSString stringWithFormat:@"%@/%@", _cur_dir, [dict valueForKey:@"name"]];
716            wchar_t *path = conv_NSString_to_wchar(_cur_dir);
717            addFDSNs_to_list(_cur_dir, FALSE, _FileDSN_ArrController);
718            fill_dir_menu(path, _popup_dir_btn);
719            if (path) free(path);
720        }
721        [self.window makeKeyAndOrderFront:self.window];
722    }
723}
724
725- (IBAction)call_FileDSN_Test:(id)sender {
726    NSArray *item = [_FileDSN_ArrController selectedObjects];
727    if (item!=nil && item.count>0){
728        NSDictionary *dict = [item objectAtIndex:0];
729        NSNumber *isdir = [dict valueForKey:@"isdir"];
730        if (isdir.boolValue==FALSE){
731            test_file_dsn(_cur_dir, [dict valueForKey:@"name"]);
732        }
733        [self.window makeKeyAndOrderFront:self.window];
734    }
735}
736
737- (IBAction)call_FileDSN_SetDir:(id)sender {
738    setdir_file_dsn(_cur_dir);
739    [self.window makeKeyAndOrderFront:self.window];
740}
741
742
743- (IBAction)call_Drv_Add:(id)sender {
744    wchar_t connstr[4096] = { L'\0' }, tokenstr[4096] = { L'\0' };
745    wchar_t *cstr;
746
747    cstr = (LPWSTR)create_driversetupw (NULL, (LPCWSTR)connstr, TRUE, TRUE);
748    if (cstr && cstr != connstr && cstr != (LPWSTR)- 1L)
749    {
750        SQLSetConfigMode (!wcscmp(cstr, L"USR") ? ODBC_USER_DSN : ODBC_SYSTEM_DSN);
751        if (!SQLInstallDriverExW (cstr + 4, NULL, tokenstr,
752                                  sizeof (tokenstr) / sizeof(wchar_t), NULL, ODBC_INSTALL_COMPLETE, NULL))
753        {
754            _iodbcdm_errorboxw ((void*)1L, NULL, L"An error occurred when trying to add the driver");
755            goto done;
756        }
757
758        free (cstr);
759    }
760
761    addDrivers_to_list(_Drv_ArrController);
762done:
763    [self.window makeKeyAndOrderFront:self.window];
764    return;
765}
766
767
768- (IBAction)call_Drv_Remove:(id)sender {
769    wchar_t tokenstr[4096] = { L'\0' };
770
771    NSArray *item = [_Drv_ArrController selectedObjects];
772    if (item!=nil && item.count>0){
773        int dsns = 0;
774        NSDictionary *dict = [item objectAtIndex:0];
775        wchar_t *wdrv = conv_NSString_to_wchar([dict valueForKey:@"name"]);
776
777        if (wdrv) {
778            /* Initialize some values */
779            SQLSetConfigMode (ODBC_USER_DSN);
780            if (SQLGetPrivateProfileStringW (wdrv, NULL, L"", tokenstr, sizeof (tokenstr)/sizeof(wchar_t), L"odbcinst.ini"))
781                dsns |= 1;
782            SQLSetConfigMode (ODBC_SYSTEM_DSN);
783            if (SQLGetPrivateProfileStringW (wdrv, NULL, L"", tokenstr, sizeof (tokenstr)/sizeof(wchar_t), L"odbcinst.ini"))
784                dsns |= 2;
785
786            IODBCadm_DrvRemoveController *dlg = [[IODBCadm_DrvRemoveController alloc] initWithDSNS:dsns];
787            NSInteger rc = [NSApp runModalForWindow:dlg.window];
788            if (rc == 1) {
789
790                if (create_confirmw ((void*)1L, wdrv, L"Are you sure you want to perform the removal of this driver ?"))
791                {
792                    if ((dlg.dsns & 1) > 0)
793                    {
794                        SQLSetConfigMode (ODBC_USER_DSN);
795                        if (!SQLRemoveDriverW (wdrv, dlg.deletedsn, NULL))
796                        {
797                            _iodbcdm_errorboxw ((void*)1L, wdrv,
798                                                L"An error occurred when trying to remove the driver ");
799                            goto done;
800                        }
801                    }
802
803                    if ((dlg.dsns & 2) > 0)
804                    {
805                        SQLSetConfigMode (ODBC_SYSTEM_DSN);
806                        if (!SQLRemoveDriverW (wdrv, dlg.deletedsn, NULL))
807                        {
808                            _iodbcdm_errorboxw ((void*)1L, wdrv,
809                                                L"An error occurred when trying to remove the driver ");
810                            goto done;
811                        }
812                    }
813                done:
814                    addDrivers_to_list(_Drv_ArrController);
815                }
816            }
817
818            free(wdrv);
819            [dlg.window orderOut:dlg.window];
820            [dlg release];
821        }
822        [self.window makeKeyAndOrderFront:self.window];
823    }
824}
825
826
827- (IBAction)call_Drv_Config:(id)sender {
828    wchar_t tokenstr[4096] = { L'\0' };
829    UWORD conf = ODBC_USER_DSN;
830
831    NSArray *item = [_Drv_ArrController selectedObjects];
832    if (item!=nil && item.count>0){
833        NSDictionary *dict = [item objectAtIndex:0];
834        wchar_t *wdrv = conv_NSString_to_wchar([dict valueForKey:@"name"]);
835
836        if (wdrv) {
837            wchar_t *curr, *cour, *cstr;
838            wchar_t connstr[4096] = { L'\0' };
839            int size = sizeof (connstr) / sizeof(wchar_t);
840
841            SQLSetConfigMode (ODBC_USER_DSN);
842            if (!SQLGetPrivateProfileStringW (wdrv, NULL, L"", tokenstr,
843                                              sizeof (tokenstr) / sizeof(wchar_t), L"odbcinst.ini"))
844            {
845                SQLSetConfigMode (conf = ODBC_SYSTEM_DSN);
846                if (!SQLGetPrivateProfileStringW (wdrv, NULL, L"", tokenstr,
847                                                  sizeof (tokenstr) / sizeof(wchar_t), L"odbcinst.ini"))
848                {
849                    _iodbcdm_errorboxw ((void*)1L, wdrv,
850                                        L"An error occurred when trying to configure the driver ");
851                    goto done;
852                }
853            }
854
855            for (curr = tokenstr, cour = connstr; *curr != L'\0' ;
856                 curr += (wcslen (curr) + 1), cour += (wcslen(cour) + 1))
857            {
858                wcscpy (cour, curr);
859                cour[wcslen (curr)] = L'=';
860                SQLSetConfigMode (conf);
861                SQLGetPrivateProfileStringW (wdrv, curr, L"",
862                                             cour + wcslen(curr) + 1, (int)(size - wcslen(curr) - 1),
863                                             L"odbcinst.ini");
864                size -= (wcslen(cour) + 1);
865            }
866
867            *cour = L'\0';
868
869            cstr = (LPWSTR)create_driversetupw (wdrv, (LPCWSTR)connstr, FALSE, (conf == ODBC_SYSTEM_DSN) ? FALSE : TRUE);
870            if (cstr && cstr != connstr && cstr != (LPWSTR) - 1L)
871            {
872                SQLSetConfigMode (conf);
873                if (!SQLInstallDriverExW (cstr + 4, NULL, tokenstr,
874                                          sizeof (tokenstr) / sizeof(wchar_t), NULL,
875                                          ODBC_INSTALL_COMPLETE, NULL))
876                {
877                    _iodbcdm_errorboxw ((void*)1L, NULL,
878                                        L"An error occurred when trying to configure the driver ");
879                    goto done;
880                }
881                free (cstr);
882            }
883
884        done:
885            addDrivers_to_list(_Drv_ArrController);
886            free(wdrv);
887        }
888        [self.window makeKeyAndOrderFront:self.window];
889    }
890}
891
892
893- (IBAction)call_Trace_Apply:(id)sender {
894    int mode;
895    wchar_t *tmp;
896
897    /* Clear previous setting */
898    SQLSetConfigMode (ODBC_USER_DSN);
899    SQLWritePrivateProfileString ("ODBC", "Trace", NULL, NULL);
900    SQLSetConfigMode (ODBC_USER_DSN);
901    SQLWritePrivateProfileString ("ODBC", "TraceAutoStop", NULL, NULL);
902    SQLSetConfigMode (ODBC_USER_DSN);
903    SQLWritePrivateProfileString ("ODBC", "TraceFile", NULL, NULL);
904    SQLSetConfigMode (ODBC_USER_DSN);
905    SQLWritePrivateProfileString ("ODBC", "TraceDLL", NULL, NULL);
906
907    SQLSetConfigMode (ODBC_SYSTEM_DSN);
908    SQLWritePrivateProfileString ("ODBC", "Trace", NULL, NULL);
909    SQLSetConfigMode (ODBC_SYSTEM_DSN);
910    SQLWritePrivateProfileString ("ODBC", "TraceAutoStop", NULL, NULL);
911    SQLSetConfigMode (ODBC_SYSTEM_DSN);
912    SQLWritePrivateProfileString ("ODBC", "TraceFile", NULL, NULL);
913    SQLSetConfigMode (ODBC_SYSTEM_DSN);
914    SQLWritePrivateProfileString ("ODBC", "TraceDLL", NULL, NULL);
915
916    mode = _rb_TraceWide.selectedRow == 0 ? ODBC_USER_DSN : ODBC_SYSTEM_DSN;
917
918    /* Write keywords for tracing in the ini file */
919    SQLSetConfigMode(mode);
920    if (_rb_WhenToTrace.selectedRow == 1 || _rb_WhenToTrace.selectedRow == 2)
921        SQLWritePrivateProfileString ("ODBC", "Trace", "1", NULL);
922    else
923        SQLWritePrivateProfileString ("ODBC", "Trace", "0", NULL);
924
925    SQLSetConfigMode(mode);
926    if (_rb_WhenToTrace.selectedRow == 2)
927        SQLWritePrivateProfileString ("ODBC", "TraceAutoStop", "1", NULL);
928    else
929        SQLWritePrivateProfileString ("ODBC", "TraceAutoStop", "0", NULL);
930
931    tmp = conv_NSString_to_wchar(_fld_LogFilePath.stringValue);
932    if (tmp)
933    {
934        SQLSetConfigMode(mode);
935        SQLWritePrivateProfileStringW (L"ODBC", L"TraceFile", tmp, NULL);
936        free(tmp);
937    }
938
939    tmp = conv_NSString_to_wchar(_fld_CustomTrace.stringValue);
940    if (tmp)
941    {
942        SQLSetConfigMode(mode);
943        SQLWritePrivateProfileStringW (L"ODBC", L"TraceDLL", tmp, NULL);
944        free(tmp);
945    }
946}
947
948- (IBAction)call_LogFilePath_Browse:(id)sender {
949    NSSavePanel *panel = [NSSavePanel savePanel];
950
951    NSURL *file_url = [NSURL fileURLWithPath:_fld_LogFilePath.stringValue];
952    NSString *fpath = file_url.path;
953    NSString *fname = file_url.lastPathComponent;
954    NSString *dir = [fpath substringToIndex:(fpath.length - fname.length)];
955
956    [panel setTitle:@"Choose your trace file ..."];
957    [panel setNameFieldStringValue:fname];
958    [panel setDirectoryURL:[NSURL fileURLWithPath:dir isDirectory:TRUE]];
959    NSInteger rc = [panel runModal];
960    if (rc==NSFileHandlingPanelOKButton)
961        [_fld_LogFilePath setStringValue:[NSString stringWithFormat:@"%@/%@", panel.directoryURL.path, panel.nameFieldStringValue]];
962    [self.window makeKeyAndOrderFront:self.window];
963}
964
965- (IBAction)call_CustomTrace_Browse:(id)sender {
966    NSOpenPanel *panel = [NSOpenPanel openPanel];
967
968    NSURL *file_url = [NSURL fileURLWithPath:_fld_CustomTrace.stringValue];
969    NSString *fpath = file_url.path;
970    NSString *fname = file_url.lastPathComponent;
971    NSString *dir = [fpath substringToIndex:(fpath.length - fname.length)];
972
973
974    [panel setTitle:@"Choose your trace library ..."];
975    [panel setNameFieldStringValue:(fname.length>0)? fname: @"ODBC Trace Library"];
976    if (dir.length>0)
977        [panel setDirectoryURL:[NSURL fileURLWithPath:dir isDirectory:TRUE]];
978    panel.allowsMultipleSelection = FALSE;
979    panel.canChooseDirectories = FALSE;
980
981    NSInteger rc = [panel runModal];
982    if (rc==NSFileHandlingPanelOKButton)
983        [_fld_CustomTrace setStringValue: ((NSURL*)[panel.URLs objectAtIndex:0]).path];
984    [self.window makeKeyAndOrderFront:self.window];
985}
986
987
988
989@end
990