1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #if defined(DXD_LICENSED_VERSION)
10 fjdasjfasjhsjasf
11 #endif
12 
13 #include <dxconfig.h>
14 
15 
16 #include <DXStrings.h>
17 
18 // This nonsense surrounds sys/types.h because its typedef for boolean conflicts
19 // with one from defines.h.  Many includes are ifdef on ARCH because of the
20 // need for select().
21 #if defined(solaris)
22 #define boolean bool
23 #endif
24 
25 #include <sys/types.h>
26 
27 #if defined(solaris)
28 #undef boolean
29 #endif
30 
31 #include <stdio.h>
32 #include <time.h>
33 
34 #if defined(HAVE_UNISTD_H)
35 #include <unistd.h>
36 #endif
37 
38 #if defined(sgi)
39 #include <bstring.h>
40 #endif
41 
42 #if defined(ibm6000)
43 #include <sys/select.h>
44 #endif
45 
46 #if defined(HAVE_SYS_UTSNAME_H)
47 #include <sys/utsname.h>
48 #endif
49 
50 #if defined(HAVE_SYS_TIMEB_H)
51 #include <sys/timeb.h>
52 #elif defined(HAVE_SYS_TIME_H)
53 #include <sys/time.h>
54 #endif
55 
56 #if defined(_AIX41)
57 #include <strings.h>
58 #endif
59 
60 #if defined(aviion)
61 extern "C" { void bzero(char *, int); }
62 #endif
63 
64 #include <X11/Intrinsic.h>
65 
66 #include "IBMApplication.h"
67 
68 #include "License.h"
69 
70 #if defined(DXD_LICENSED_VERSION) && DXD_LICENSED_VERSION!=0
71 # define NEEDS_LICENSE_ROUTINES 1
72 #else
73 # define NEEDS_LICENSE_ROUTINES 0
74 #endif
75 
76 #if NEEDS_LICENSE_ROUTINES
77 
78 extern "C" {
79 
80 
81 #if (defined(sgi) && !( __mips > 1)) || defined(aviion)
82 const char *crypt(const char*, const char*);
83 #endif
84 
85 #if defined(solaris)
86 #include <crypt.h>
87 #endif
88 
89 #ifdef sun4
90 int gethostid();
91 int getdtablesize();
92 #endif
93 
94 
95 #ifdef sgi
96 unsigned sysid(unsigned char id[]);
97 int getdtablesize(void);
98 #endif
99 
100 
101 #if defined(aviion)
102 int gethostid();
103 int getdtablesize();
104 int gettimeofday(struct timeval*, struct timezone*);
105 #endif
106 
107 #ifdef alphax
108 #include <crypt.h>
109 int getdtablesize();
110 #include <stdio.h>              /* standard I/O */
111 #include <errno.h>              /* error numbers */
112 
113 #if defined(windows) && defined(HAVE_WINSOCK_H)
114 #include <winsock.h>
115 #elif defined(HAVE_CYGWIN_SOCKET_H)
116 #include <cygwin/socket.h>
117 #elif defined(HAVE_SYS_SOCKET_H)
118 #include <sys/socket.h>
119 #endif
120 
121 #include <sys/ioctl.h>          /* ioctls */
122 #include <net/if.h>             /* generic interface structures */
123 #include <sys/systeminfo.h>  /* maybe someday this will be implemented...arg! */
124 extern "C"   int select(
125           int nfds,
126           fd_set *readfds,
127           fd_set *writefds,
128           fd_set *exceptfds,
129           struct timeval *timeout) ;
130 #endif
131 
132 }
133 #define CRYPT(A,B) crypt((const char*)A, (const char*)B)
134 
135 #define ANYWHERE_HOSTID "00000000"
136 
137 #if defined(DXD_LICENSED_VERSION) && !defined(HAVE_CRYPT)
138   error:  Can not  run licensing routines without crypt()
139 #endif
140 
141 static int  checkexp(const char *root);
142 
143 #endif // NEEDS_LICENSE_ROUTINES
144 
145 #ifndef DXD_WIN
146 
UIGetLicense(const char * root,XtInputCallbackProc lostLicense,LicenseTypeEnum * appLic,LicenseTypeEnum * funcLic)147 void UIGetLicense(const char *root,
148 			XtInputCallbackProc lostLicense,
149 			LicenseTypeEnum *appLic,
150 			LicenseTypeEnum *funcLic)
151 {
152 #if !NEEDS_LICENSE_ROUTINES
153     *appLic = FullyLicensed;
154     *funcLic = FullFunctionLicense;
155     return;
156 #else
157 
158     LicenseTypeEnum forcedFuncLic;
159     int i;
160     int child;
161     int child_in[2],child_out[2];
162     char remname[1024];
163     char auth_msg[AUTH_MSG_LEN];
164     char ckey[128];
165     char c_buf[128],p_buf[128];	/* hold crypted msgs for comaparison */
166     char envbuf[128];
167     char salt[32];
168     time_t ctime;
169 
170 
171     if (checkexp (root)) { /* check for an old syle trial license */
172 	*appLic = NodeLockedLicense;
173         *funcLic = FullFunctionLicense;
174 	return;
175     }
176 
177 
178     /* didn't find a trial license so spawn the NetLS licensing process */
179     *appLic = Unlicensed;
180     forcedFuncLic = *funcLic;
181     *funcLic = Unlicensed;
182 
183     /* Set up two pipes */
184     if (pipe(child_in) < 0) {
185         perror("pipe(child_in)");
186 	return;
187     }
188 
189     if (pipe(child_out) < 0) {
190         perror("pipe(child_out)");
191 	return ;
192     }
193 
194     ctime=time(NULL);
195 
196     sprintf(envbuf,"_DX_%d=",getpid());
197     sprintf(c_buf,"%x",ctime);
198     strcat(envbuf,c_buf+4);
199     putenv(DuplicateString(envbuf));
200 
201 
202     child = 0xffff&fork();
203 
204 
205     if (child == 0) {	/* Child */
206 
207       char arg1[512];
208       char arg2[512];
209       char arg3[512];
210 #ifdef hp700
211     int  width = MAXFUPLIM;
212 #else
213 #ifdef solaris
214     int  width = FD_SETSIZE;
215 #else
216     int  width = getdtablesize();
217 #endif
218 #endif
219 
220       close(child_in[1]);
221       close(child_out[0]);
222 
223       if (dup2(child_in[0], 0) < 0)
224 	exit(1);
225 
226       if (dup2(child_out[1], 1) < 0)
227 	exit(1);
228 
229       /* close other file descriptors here  */
230 #if !defined(__PURIFY__)
231       // purify uses some file descriptors
232       for (i=3 ; i<=width ; i++)
233 	   close(i);
234 #endif
235 
236       char *s;
237       if (s = getenv("DXSHADOW"))
238 	strcpy(remname,s);
239       else
240 	sprintf(remname,"%s/bin_%s/dxshadow",root,DXD_ARCHNAME);
241 
242       switch (forcedFuncLic) {
243             case RunTimeLicense: strcpy(arg1,"-rtonly");      break;
244             case DeveloperLicense: strcpy(arg1,"-devonly");     break;
245             default:    strcpy(arg1,"-dev"); break;
246       }
247       int maj, min,mic;
248       theIBMApplication->getVersionNumbers(&maj,&min,&mic);
249       sprintf(arg3,"%d.%d.%d",maj,min,mic);
250 
251       execlp(remname, "dxshadow", arg1, "-version", arg3, NULL);
252 
253       //
254       // If we get here, we failed.
255       //
256       fprintf(stderr,"License Error: could not exec license process\n");
257       exit(1);
258     }
259 
260     //
261     // Only the parent gets here
262     //
263     close (child_in[0]);
264     close (child_out[1]);
265 
266     /* wait for response from the child */
267 
268 #define USE_SUB_EVENT_LOOP 1
269 #if USE_SUB_EVENT_LOOP
270     // Instead of doing a blocking read... and instead of writing a communication
271     // subsystem, monitor all sockets of interest.  When something arrives, service
272     // it.  As a result, X Events still get processed and we achieve a little extra
273     // concurrency which should decrease startup time.  According to Quantify,
274     // we were spending lots of time inside the call to read().
275     // The loop waits approximately 5 seconds.  If dxshadow takes longer than that,
276     // then execution continues by sitting in the read() command as it used to.
277     fd_set rdfds;
278     XEvent event;
279     FD_ZERO(&rdfds);
280     Display *d = theApplication->getDisplay();
281     XtAppContext app = theApplication->getApplicationContext();
282     timeval tval, starttime;
283     gettimeofday (&starttime, NULL);
284     while (!FD_ISSET(child_out[0], &rdfds)) {
285 	FD_SET (child_out[0], &rdfds);
286 	FD_SET (ConnectionNumber(d), &rdfds);
287 	tval.tv_sec = 1; tval.tv_usec = 0;
288 	if (select (32, (SELECT_ARG_TYPE *)&rdfds, NULL, NULL, &tval) == -1) break;
289 	XtInputMask mask;
290 	while ((mask = XtAppPending (app)) & (XtIMXEvent|XtIMTimer)) {
291 	    if (XtIMXEvent & mask) {
292 		XtAppNextEvent (app, &event);
293 		theIBMApplication->passEventToHandler (&event);
294 	    }
295 	    if (XtIMTimer & mask) {
296 		XtAppProcessEvent (app, XtIMTimer);
297 	    }
298 	}
299 	if (gettimeofday (&tval, NULL) == -1) break;
300 	if ((tval.tv_sec - starttime.tv_sec) >= 10) break;
301     }
302 #endif
303     i = read(child_out[0],auth_msg,AUTH_MSG_LEN);
304 
305     if (!i) {
306 	fprintf(stderr,"License Error\n");
307 	goto unlicensed;
308     }
309 
310     /* decipher license message here */
311 
312     child = (child<4096)?(child+4096):(child); /* forces to be 4 0x chars */
313 
314     strcpy(ckey,c_buf+4);
315     sprintf(ckey+4,"%x",child);
316 
317     salt[0] = '7';
318     salt[1] = 'q';
319     salt[2] = '\0';
320 
321     strcpy(p_buf,CRYPT(ckey,salt));;
322 
323     for(i=0;i<13;i++)
324 	c_buf[i] = auth_msg[(i*29)+5];
325     c_buf[13] = '\0';
326 
327     if (strcmp(c_buf,p_buf)) {
328 
329 	/* Bad message from child */
330 
331 	fprintf(stderr,"License error\n");
332 	goto unlicensed;
333     }
334 
335     /* valid message so we extract license type */
336 
337     for(i=0;i<8;i++)
338 	  c_buf[i] = auth_msg[(i*3)+37];
339 
340     c_buf[8] = '\0';
341 
342     sscanf(c_buf,"%x",&i);
343     *appLic = (LicenseTypeEnum)(0xffff & (i^child));
344     i = i >> 16;
345     *funcLic = (LicenseTypeEnum)(0xffff & (i^child));
346 #if 000
347     fprintf(stderr,"c_buf = '%s', funcLic = 0x%x, appLic = 0x%x\n",
348 			    c_buf,*funcLic,*appLic);
349 #endif
350 
351     const char* lic_name;
352     switch (*funcLic) {
353 	case DeveloperLicense: lic_name = "DX development"; break;
354 	case RunTimeLicense:   lic_name = "DX run-time"; break;
355 	default:
356 	        fprintf(stderr,"Unrecognized license\n");
357 	        goto unlicensed;
358 		break;
359     }
360 
361     switch (*appLic) {
362 
363 	case NodeLockedLicense:
364 
365 #ifdef DEBUG
366 	      fprintf(stderr,"Got nodelocked %s license\n",lic_name);
367 #endif
368 	      return;
369 
370 	case ConcurrentLicense:
371 
372 #ifdef DEBUG
373 	      fprintf(stderr,"Got concurrent %s license\n",lic_name);
374 #endif
375 
376 	      XtAppAddInput(theIBMApplication->getApplicationContext(),
377 			child_out[0],
378 			(XtPointer)(XtInputReadMask),
379 			lostLicense,
380 			(XtPointer)NULL);
381 
382 	      return ;
383 
384 
385 	case Unlicensed:
386 
387 #ifdef DEBUG
388 	      fprintf(stderr,"Could not get a license\n");
389 #endif
390 	      break;
391 
392 
393 	default: 	/* invalid license type */
394 #ifdef DEBUG
395 
396 	      fprintf(stderr,"License Error: Invalid License Type\n");
397 #endif
398 	      goto unlicensed;
399     }
400 
401 
402 unlicensed:
403     *appLic = Unlicensed;
404     *funcLic = Unlicensed;
405     return;
406 
407 #endif // NEEDS_LICENSE_ROUTINES
408 }
409 
410 
411 
412 
413 
414 
415 /* This function creates the message which will tell the exec if it
416  * is OK to run without a license. inkey must be at least char[14]
417  * and should contain the key returned from the $getkey.  type
418  * should be either ConcurrentLicense or NodeLockedLicense. On return
419  * inkey holds the string to send to the exec with $license.
420  * The returned string must be freed by the caller.
421  */
422 
GenerateExecKey(const char * inkey,LicenseTypeEnum licenseType)423 char *GenerateExecKey(const char *inkey, LicenseTypeEnum licenseType)
424 {
425 
426 #if NEEDS_LICENSE_ROUTINES
427 
428     int i;
429     char keybuf[64];
430     char cryptbuf[64];
431     char salt[8];
432 
433     for(i=0;i<4;i++)
434       keybuf[i*2]=inkey[i];
435 
436     keybuf[1] = 'g';
437     keybuf[3] = '3';
438     keybuf[5] = '$';
439     keybuf[7] = 'Q';
440     keybuf[8] = '\0';
441 
442     salt[0] = '4';
443     salt[1] = '.';
444     salt[2] = '\0';
445 
446     strcpy(cryptbuf,CRYPT(keybuf,salt));
447 
448     char *outkey = new char[64];
449     sprintf(outkey,"%s%hx",cryptbuf,
450 			(unsigned short)licenseType ^
451 			(*((unsigned char *)&cryptbuf[4])<<8)+(*((unsigned char *)&cryptbuf[5])));
452 
453     return outkey;
454 #else
455     return NULL;
456 #endif // NEEDS_LICENSE_ROUTINES
457 
458 }
459 
460 
461 
462 
463 #if NEEDS_LICENSE_ROUTINES
464 
465 #define KEY1 "a9"
466 #define KEY2 "Pp"
467 
468 #if defined(aviion) || defined(solaris)
469 #include <sys/systeminfo.h>
470 #if defined(aviion)
471 extern "C" {
472  long sysinfo (int command, char *buf, long count);
473 }
474 #endif
475 #endif
476 
477 #ifdef alphax
478 extern "C" int gethostid(void);
479 #endif
480 
checkexp(const char * root)481 static int  checkexp(const char *root)
482 {
483 #if !DXD_HAS_CRYPT
484   return (1);
485 #else
486   int	host_match;
487   char   key[32];
488   char   cryptHost[1024];
489   char   cryptTime[1024];
490   char   host[512];
491   time_t timeOut;
492   int    i;
493   char  *myCryptHost;
494   struct timeval sysTime;
495 #if defined(ibm6000) || defined(hp700)
496   struct utsname name;
497 #endif
498 #if defined(sgi) || defined(sun4)   || defined (alphax)
499   long   name;
500 #endif
501   time_t time;
502   char   fileName[1024];
503   FILE   *f;
504 
505   for (i = 0; i < sizeof(key); ++i)
506     key[i] = '\0';
507 
508 #ifdef ibm6000
509 #define FOUND_ID 1
510   uname(&name);
511   name.machine[10] = '\0';
512   strcpy(host, name.machine+2);
513 #endif
514 #if hp700
515 #define FOUND_ID 1
516   uname(&name);
517   name.idnumber[10] = '\0';
518   strcpy(host, name.idnumber+2);
519 #endif
520 #if sgi              /* sgi does not like #if...#elif..#endif construct */
521 #define FOUND_ID 1
522   name = sysid(NULL);
523   sprintf(host, "%d", name);
524   strcpy(host, host+2);
525 #endif
526 #if sun4
527 #define FOUND_ID 1
528   name = gethostid();
529   sprintf(host, "%x", name);
530 #endif
531 #if aviion
532 #define FOUND_ID 1
533   sysinfo(SI_HW_SERIAL,host,301);
534 #endif
535 #if solaris
536 #define FOUND_ID 1
537     sysinfo(SI_HW_SERIAL,host,301);
538     sprintf(host, "%x", atol(host));
539 #endif
540 #if defined(alphax)
541 #ifdef SYSINFO_WORKS
542 // The man page for OSF/1 V2 says that SI_HW_SERIAL does not work.  We'll use it
543 // for now even though it doesn't work.  So far it looks like the only mechanism
544 // to get unique ids.
545     sysinfo(SI_HW_SERIAL,host,301);
546     sprintf(host, "%x", atol(host));
547 #else
548 {
549     char *device;
550     char *dflt_devices[] = {"tu0","ln0", NULL };
551     int s,i;                             /* On Alpha OSF/1 we use ethernet */;
552 
553     /* Get a socket */
554     strcpy(host,"");
555     s = socket(AF_INET,SOCK_DGRAM,0);
556     if (s < 0) {
557         perror("socket");
558     } else {
559 	for (i=0, device=(char*)getenv("DXKEYDEVICE"); dflt_devices[i]; i++) {
560 	    static   struct  ifdevea  devea; /* MAC address from and ioctl() */
561 	    char *dev, buf[32];
562 	    if (!device)
563 		dev = dflt_devices[i];
564 	    else
565 		dev = device;
566 	    strcpy(devea.ifr_name,dev);
567 	    if (ioctl(s,SIOCRPHYSADDR,&devea) >= 0)  {
568 		strcpy(host,"");
569 		for (i = 2; i < 6; i++){
570 		    sprintf(buf,"%x", devea.default_pa[i] );
571 		    strcat(host,buf);
572 		}
573 		break;
574 	    }
575 	    if (device) break;
576 	}
577 	close(s);
578     }
579 }
580 
581 #endif
582 #define FOUND_ID 1
583 #endif
584 #if !defined(FOUND_ID)
585   Trial version not supported on this architecture.
586 #else
587 # undef FOUND_ID
588 #endif
589 
590   gettimeofday(&sysTime, NULL);
591   time = sysTime.tv_sec;
592 
593   if (getenv("DXTRIALKEY")) {
594 	char *k = getenv("DXTRIALKEY");
595 	fprintf(stderr, "Data Explorer trial password found in"
596 		    " DXTRIALKEY environment variable\n");
597 	strncpy(key,k,27);
598         key[27] = '\0';	// Make sure it is terminated
599   } else {
600       char *fname;
601       fname = getenv("DXTRIALKEYFILE");
602       if (!fname) {
603 	  sprintf(fileName, "%s/expiration", root);
604 	  fname = fileName;
605       }
606       f = fopen(fname, "r");
607       if (f)  {
608 	fprintf(stderr, "Data Explorer trial password found in file %s\n",
609 							fname);
610 	fgets(key, 27, f);
611 	fclose(f);
612       } else {
613 	return 0;
614       }
615   }
616 
617 
618   if (strlen(key) != 26) {
619     fprintf(stderr, "You are running an expired Trial version of Data Explorer\n");
620     return(0);
621   }
622 
623   for (i = 0; i < 13; ++i) {
624     cryptHost[i] = key[2 * i];
625     cryptTime[i] = key[2 * i + 1];
626   }
627   cryptHost[i] = key[2 * i] = '\0';
628   cryptTime[i] = key[2 * i + 1] = '\0';
629 
630   if (cryptTime[0] != 'A' ||
631       cryptTime[10] != '9' ||
632       cryptTime[12] != 'D') {
633     fprintf(stderr, "You are running an Expired trial version of Data Explorer\n");
634     return(0);
635   }
636 
637 
638   myCryptHost = (char*)CRYPT(host,KEY1);
639   host_match = strcmp(cryptHost, myCryptHost) == 0;
640   if (!host_match) {
641 	myCryptHost = (char*)CRYPT(ANYWHERE_HOSTID,KEY1);
642         host_match = strcmp(cryptHost, myCryptHost) == 0;
643   }
644   if (!host_match) {
645     fprintf(stderr,
646 	"You are running a trial version of Data Explorer on an"
647 	" unlicensed host\n");
648     return (0);
649   }
650 
651   if(cryptTime[1]=='s')
652      sscanf(cryptTime, "As%08x95D", &timeOut);
653   else if (cryptTime[1]=='m')
654      sscanf(cryptTime, "Am%08x9lD", &timeOut);
655 
656 
657 timeOut ^= 0x12345678;
658 
659   if (time > timeOut) {
660     fprintf(stderr, "You are running an expired trial version of Data Explorer\n");
661     fprintf(stderr,"This trial key expired on %s", ctime(&timeOut));
662     return (0);
663   }
664   fprintf(stderr,"This Data Explorer trial key will expire on %s",
665 				ctime(&timeOut));
666   return (1);
667 #endif /* DXD_HAS_CRYPT */
668 }
669 
670 #ifdef ibm6000
671 // Some very strange declarations that allow AIX 3.2.4 systems to link.
672 // These symbols are statics inside of "crypt.c" in /usr/lib/libc.a, but
673 // are referenced in the mapping defined for the shared library.  Therefore,
674 // the system won't link without them.
675 extern "C" char __setkey[1024];
676 extern "C" char __crypt[1024];
677 extern "C" char __encrypt[1024];
678 char __setkey[1024];
679 char __crypt[1024];
680 char __encrypt[1024];
681 #endif
682 
683 #endif // NEEDS_LICENSE_ROUTINES
684 
685 #else  // DXD_WIN
686 #if 0
687 
688 #include <windows.h>
689 #include <math.h>
690 
691 static int getregval(char *name, char *value)
692 {
693     char key[500];
694     int valtype;
695     unsigned long sizegot = 500;
696     int word;
697     char errstr[200];
698     HKEY hkey[10];
699     long rc;
700     int i, k=0;
701 
702 #define iferror(s)	\
703     if (rc != ERROR_SUCCESS) {	\
704 	strcpy(errstr, s);	\
705 	goto error;		\
706     }
707 
708     strcpy(value, "");
709     word = 0;
710     strcpy(key, "SOFTWARE");
711 
712     rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR) key, 0,
713 	KEY_QUERY_VALUE, &hkey[k++]);
714 
715     strcat(key, "\\OpenDX");
716     rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR) key, 0,
717 	KEY_QUERY_VALUE, &hkey[k++]);
718     iferror("Error opening key");
719 
720     strcat(key, "\\Open Visualization Data Explorer");
721     rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR) key, 0,
722 	KEY_QUERY_VALUE, &hkey[k++]);
723     iferror("Error opening key");
724 
725     strcat(key, "\\CurrentVersion");
726     rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR) key, 0,
727 	KEY_QUERY_VALUE, &hkey[k++]);
728     iferror("Error opening key");
729 
730     rc = RegQueryValueEx(hkey[k-1], (LPTSTR) name, (LPDWORD) 0,
731 	(LPDWORD) &valtype, (LPBYTE) value, &sizegot);
732     iferror("Query value failed");
733 
734     for (i=k; i > 0; i--) {
735 	rc = RegCloseKey(hkey[i-1]);
736 	iferror("CloseKey failed");
737     }
738 
739     switch(valtype) {
740 	case REG_DWORD:
741 	    word = *((int *)value);
742 	    value = "";
743 	    break;
744 	case REG_SZ:
745 	    break;
746 	default:
747 	    return 0;
748     }
749 
750     return 1;
751 
752 error:
753     fprintf(stderr, "%s: rc = %d\n", errstr, rc);
754     return 0;
755 }
756 
757 static int keyformat(char *k)
758 {
759     int i;
760     char buf[25];
761     char *p;
762 
763     for (i=0, p=k; *p && i<20; p++) {
764 	if (isalpha(*p))
765 	    buf[i++] = tolower(*p);
766 	if (isdigit(*p))
767 	    buf[i++] = *p;
768 	if (i==5 || i==10 || i==15)
769 	    buf[i++] = ' ';
770     }
771     buf[i] = '\0';
772     if (strlen(buf) != 20)
773 	return 0;
774     strcpy(k, buf);
775     return 1;
776 }
777 
778 int getuserinforeg(char *username, char *userco, char *keystr)
779 {
780     *username = '\0';
781     *userco = '\0';
782     *keystr = '\0';
783     getregval("UserName", username);
784     getregval("CompanyName", userco);
785     getregval("LicenseKey", keystr);
786     keyformat(keystr);
787     return 1;
788 }
789 
790 static int gettimenow(int *m, int *d, int *y)
791 {
792     SYSTEMTIME t;
793     GetSystemTime(&t);
794     *m = t.wMonth;
795     *d = t.wDay;
796     *y = t.wYear;
797     return 1;
798 }
799 
800 static int addtotime(int *m, int *d, int *y)
801 {
802     int mm, dd, yy;
803 
804     gettimenow(&mm, &dd, &yy);
805     *y += yy;
806     *m += mm;
807     if (*m>12) {
808 	*y += (*m-1)/12;
809 	*m = *m%12 + 1;
810     }
811     *d += dd;
812     if (*d > 28) {
813 	(*m)++;
814 	*d = *d%31;
815     }
816     if (*m>12) {
817 	*y += (*m-1)/12;
818 	*m = *m%12 + 1;
819     }
820     return 1;
821 }
822 
823 static int genkey(char *keystr, char *username, char *userco,
824 		    int m, int d, int y, char lictype)
825 {
826     char *p, *q;
827     unsigned int key, key1, key2, key3, prime;
828     int i;
829     char data[500];
830 
831     data[0] = (char)(m + (int)'a');
832     if (d > 20)
833 	data[0] = (char)((int)data[0] + 13);
834     data[1] = (char)(d%20 + (int)'b');
835     data[2] = (char)((y - 1994)/10 + (int)'g');
836     data[3] = (char)((y - 1994)%10 + (int)'m');
837     if (!lictype)
838 	lictype = 't';
839     data[4] = lictype;
840 
841     q = &data[5];
842     for (p=username; *p; p++)
843 	if (!isspace(*p) && !ispunct(*p))
844 	    *(q++) = tolower(*p);
845     for (p=userco; *p; p++)
846 	if (!isspace(*p) && !ispunct(*p))
847 	    *(q++) = tolower(*p);
848     *q = '\0';
849 
850     key = 99;
851     key = key * 100 + 99;
852     key = key * 100 + 83;
853 
854     prime = 4999;
855     prime = prime * 1000 + 999;
856 
857     for (i = 0, p=data; *p; p++, i++)
858 	key += (*p * (i + key)) * prime;
859 
860     key %=   10000000000;
861     key1 = key/100000000;
862     key2 = key%100000000;
863     key2 /= 10000;
864     key3 = key%10000;
865     sprintf(keystr, "%c%c%c%c%c %04d %04d %04d", data[0],
866 		data[1], data[2], data[3], data[4], key1, key2, key3);
867     return 1;
868 }
869 
870 int getdatefromkey(char *keystr, int *m, int *d, int *y)
871 {
872     *m = (int)keystr[0] - (int)'a';
873     *d = (int)keystr[1] - (int)'b';
874     if (*m > 12) {
875 	*m -= 13;
876 	*d += 20;
877     }
878     if (*d < 1)
879 	*d = 1;
880     if (*d > 31)
881 	*d = 31;
882     *y = ((int)keystr[2] - (int)'g') * 10 +
883 		(int)keystr[3] - (int)'m' + 1994;
884     return 1;
885 }
886 
887 static int isexpired(char *keystr)
888 {
889     int m, d, y;
890     int ms, ds, ys;
891 
892     gettimenow(&ms, &ds, &ys);
893     getdatefromkey(keystr, &m, &d, &y);
894     if (ys > y)
895 	return 1;
896     if (ys == y && ms > m)
897 	return 1;
898     if (ys == y && ms == m && ds > d)
899 	return 1;
900     return 0;
901 }
902 
903 void UIGetLicense(const char *root,
904 			XtInputCallbackProc lostLicense,
905 			LicenseTypeEnum *appLic,
906 			LicenseTypeEnum *funcLic)
907 {
908     char username[200];
909     char userco[200];
910     char keystrreg[100];
911     char keystr[100];
912     char lictype;
913     int m;
914     int d;
915     int y;
916     int expired;
917 
918     *appLic = Unlicensed;
919     *funcLic = Unlicensed;
920     getuserinforeg(username, userco, keystrreg);
921     if (strlen(username) + strlen(userco) < 6) {
922 	fprintf(stderr, "Improper registration: short username and company\n");
923 	return;
924     }
925     if (!keyformat(keystrreg)) {
926 	fprintf(stderr, "Improper registration: registration key is not in proper format: %s\n",
927 			    keystrreg);
928 	return;
929     }
930     fprintf(stderr, "Registered to %s of %s\n", username, userco);
931     getdatefromkey(keystrreg, &m, &d, &y);
932     lictype = keystrreg[4];
933     genkey(keystr, username, userco, m, d, y, lictype);
934     if (strcmp(keystr, keystrreg)) {
935 	fprintf(stderr, "Improper registration: key does not match user setup\n");
936 	return;
937     }
938     expired = isexpired(keystrreg);
939     if (expired) {
940 	fprintf(stderr, "Registration expired %d/%d/%d\n", m, d, y);
941 	return;
942     }
943     // Don't show expire date if license isn't beta or trial
944     if (lictype == 'b' || lictype == 't')
945 	fprintf(stderr, "Registration expires %d/%d/%d\n", m, d, y);
946     if (lictype == 'r') {
947 	*appLic = NodeLockedLicense;
948 	*funcLic = RunTimeLicense;
949     } else {
950 	*appLic = FullyLicensed;
951 	*funcLic = DeveloperLicense;
952     }
953     return;
954 }
955 
956 char *GenerateExecKey(const char *inkey, LicenseTypeEnum licenseType)
957 {
958     return "No License Generated";
959 }
960 #endif
961 #endif  // DXD_WIN
962