├── .gitignore ├── .vscode └── settings.json ├── README.md ├── nbproject ├── project.properties └── project.xml ├── phpcs.xml └── software-license-manager ├── css └── jquery-ui.css ├── includes ├── index.html ├── slm-api-listener.php ├── slm-api-utility.php ├── slm-debug-logger.php ├── slm-error-codes.php ├── slm-init-time-tasks.php ├── slm-third-party-integration.php └── slm-utility.php ├── index.html ├── js ├── index.html └── wplm-custom-admin.js ├── menu ├── includes │ └── index.html ├── index.html ├── slm-add-licenses.php ├── slm-admin-functions.php ├── slm-admin-init.php ├── slm-integration-help-page.php ├── slm-lic-settings.php ├── slm-list-licenses-class.php └── slm-manage-licenses.php ├── readme.txt ├── slm_bootstrap.php ├── slm_installer.php └── slm_plugin_core.php /.gitignore: -------------------------------------------------------------------------------- 1 | /nbproject/private/ 2 | software-license-manager/logs/ 3 | 4 | .idea 5 | software-license-manager.zip -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "phpSniffer.snippetExcludeSniffs": [ 3 | 4 | 5 | ], 6 | "phpSniffer.standard": "./phpcs.xml" 7 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | software-license-manager 2 | ======================== 3 | 4 | Full details here: 5 | https://www.tipsandtricks-hq.com/software-license-manager-plugin-for-wordpress 6 | -------------------------------------------------------------------------------- /nbproject/project.properties: -------------------------------------------------------------------------------- 1 | include.path=${php.global.include.path} 2 | php.version=PHP_54 3 | source.encoding=UTF-8 4 | src.dir=. 5 | tags.asp=false 6 | tags.short=true 7 | web.root=. 8 | -------------------------------------------------------------------------------- /nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.php.project 4 | 5 | 6 | software-license-manager 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /software-license-manager/css/jquery-ui.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.11.0 - 2014-06-26 2 | * http://jqueryui.com 3 | * Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css 4 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px 5 | * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ 6 | 7 | /* Layout helpers 8 | ----------------------------------*/ 9 | .ui-helper-hidden { 10 | display: none; 11 | } 12 | .ui-helper-hidden-accessible { 13 | border: 0; 14 | clip: rect(0 0 0 0); 15 | height: 1px; 16 | margin: -1px; 17 | overflow: hidden; 18 | padding: 0; 19 | position: absolute; 20 | width: 1px; 21 | } 22 | .ui-helper-reset { 23 | margin: 0; 24 | padding: 0; 25 | border: 0; 26 | outline: 0; 27 | line-height: 1.3; 28 | text-decoration: none; 29 | font-size: 100%; 30 | list-style: none; 31 | } 32 | .ui-helper-clearfix:before, 33 | .ui-helper-clearfix:after { 34 | content: ""; 35 | display: table; 36 | border-collapse: collapse; 37 | } 38 | .ui-helper-clearfix:after { 39 | clear: both; 40 | } 41 | .ui-helper-clearfix { 42 | min-height: 0; /* support: IE7 */ 43 | } 44 | .ui-helper-zfix { 45 | width: 100%; 46 | height: 100%; 47 | top: 0; 48 | left: 0; 49 | position: absolute; 50 | opacity: 0; 51 | filter:Alpha(Opacity=0); 52 | } 53 | 54 | .ui-front { 55 | z-index: 100; 56 | } 57 | 58 | 59 | /* Interaction Cues 60 | ----------------------------------*/ 61 | .ui-state-disabled { 62 | cursor: default !important; 63 | } 64 | 65 | 66 | /* Icons 67 | ----------------------------------*/ 68 | 69 | /* states and images */ 70 | .ui-icon { 71 | display: block; 72 | text-indent: -99999px; 73 | overflow: hidden; 74 | background-repeat: no-repeat; 75 | } 76 | 77 | 78 | /* Misc visuals 79 | ----------------------------------*/ 80 | 81 | /* Overlays */ 82 | .ui-widget-overlay { 83 | position: fixed; 84 | top: 0; 85 | left: 0; 86 | width: 100%; 87 | height: 100%; 88 | } 89 | .ui-accordion .ui-accordion-header { 90 | display: block; 91 | cursor: pointer; 92 | position: relative; 93 | margin: 2px 0 0 0; 94 | padding: .5em .5em .5em .7em; 95 | min-height: 0; /* support: IE7 */ 96 | font-size: 100%; 97 | } 98 | .ui-accordion .ui-accordion-icons { 99 | padding-left: 2.2em; 100 | } 101 | .ui-accordion .ui-accordion-icons .ui-accordion-icons { 102 | padding-left: 2.2em; 103 | } 104 | .ui-accordion .ui-accordion-header .ui-accordion-header-icon { 105 | position: absolute; 106 | left: .5em; 107 | top: 50%; 108 | margin-top: -8px; 109 | } 110 | .ui-accordion .ui-accordion-content { 111 | padding: 1em 2.2em; 112 | border-top: 0; 113 | overflow: auto; 114 | } 115 | .ui-autocomplete { 116 | position: absolute; 117 | top: 0; 118 | left: 0; 119 | cursor: default; 120 | } 121 | .ui-button { 122 | display: inline-block; 123 | position: relative; 124 | padding: 0; 125 | line-height: normal; 126 | margin-right: .1em; 127 | cursor: pointer; 128 | vertical-align: middle; 129 | text-align: center; 130 | overflow: visible; /* removes extra width in IE */ 131 | } 132 | .ui-button, 133 | .ui-button:link, 134 | .ui-button:visited, 135 | .ui-button:hover, 136 | .ui-button:active { 137 | text-decoration: none; 138 | } 139 | /* to make room for the icon, a width needs to be set here */ 140 | .ui-button-icon-only { 141 | width: 2.2em; 142 | } 143 | /* button elements seem to need a little more width */ 144 | button.ui-button-icon-only { 145 | width: 2.4em; 146 | } 147 | .ui-button-icons-only { 148 | width: 3.4em; 149 | } 150 | button.ui-button-icons-only { 151 | width: 3.7em; 152 | } 153 | 154 | /* button text element */ 155 | .ui-button .ui-button-text { 156 | display: block; 157 | line-height: normal; 158 | } 159 | .ui-button-text-only .ui-button-text { 160 | padding: .4em 1em; 161 | } 162 | .ui-button-icon-only .ui-button-text, 163 | .ui-button-icons-only .ui-button-text { 164 | padding: .4em; 165 | text-indent: -9999999px; 166 | } 167 | .ui-button-text-icon-primary .ui-button-text, 168 | .ui-button-text-icons .ui-button-text { 169 | padding: .4em 1em .4em 2.1em; 170 | } 171 | .ui-button-text-icon-secondary .ui-button-text, 172 | .ui-button-text-icons .ui-button-text { 173 | padding: .4em 2.1em .4em 1em; 174 | } 175 | .ui-button-text-icons .ui-button-text { 176 | padding-left: 2.1em; 177 | padding-right: 2.1em; 178 | } 179 | /* no icon support for input elements, provide padding by default */ 180 | input.ui-button { 181 | padding: .4em 1em; 182 | } 183 | 184 | /* button icon element(s) */ 185 | .ui-button-icon-only .ui-icon, 186 | .ui-button-text-icon-primary .ui-icon, 187 | .ui-button-text-icon-secondary .ui-icon, 188 | .ui-button-text-icons .ui-icon, 189 | .ui-button-icons-only .ui-icon { 190 | position: absolute; 191 | top: 50%; 192 | margin-top: -8px; 193 | } 194 | .ui-button-icon-only .ui-icon { 195 | left: 50%; 196 | margin-left: -8px; 197 | } 198 | .ui-button-text-icon-primary .ui-button-icon-primary, 199 | .ui-button-text-icons .ui-button-icon-primary, 200 | .ui-button-icons-only .ui-button-icon-primary { 201 | left: .5em; 202 | } 203 | .ui-button-text-icon-secondary .ui-button-icon-secondary, 204 | .ui-button-text-icons .ui-button-icon-secondary, 205 | .ui-button-icons-only .ui-button-icon-secondary { 206 | right: .5em; 207 | } 208 | 209 | /* button sets */ 210 | .ui-buttonset { 211 | margin-right: 7px; 212 | } 213 | .ui-buttonset .ui-button { 214 | margin-left: 0; 215 | margin-right: -.3em; 216 | } 217 | 218 | /* workarounds */ 219 | /* reset extra padding in Firefox, see h5bp.com/l */ 220 | input.ui-button::-moz-focus-inner, 221 | button.ui-button::-moz-focus-inner { 222 | border: 0; 223 | padding: 0; 224 | } 225 | .ui-datepicker { 226 | width: 17em; 227 | padding: .2em .2em 0; 228 | display: none; 229 | } 230 | .ui-datepicker .ui-datepicker-header { 231 | position: relative; 232 | padding: .2em 0; 233 | } 234 | .ui-datepicker .ui-datepicker-prev, 235 | .ui-datepicker .ui-datepicker-next { 236 | position: absolute; 237 | top: 2px; 238 | width: 1.8em; 239 | height: 1.8em; 240 | } 241 | .ui-datepicker .ui-datepicker-prev-hover, 242 | .ui-datepicker .ui-datepicker-next-hover { 243 | top: 1px; 244 | } 245 | .ui-datepicker .ui-datepicker-prev { 246 | left: 2px; 247 | } 248 | .ui-datepicker .ui-datepicker-next { 249 | right: 2px; 250 | } 251 | .ui-datepicker .ui-datepicker-prev-hover { 252 | left: 1px; 253 | } 254 | .ui-datepicker .ui-datepicker-next-hover { 255 | right: 1px; 256 | } 257 | .ui-datepicker .ui-datepicker-prev span, 258 | .ui-datepicker .ui-datepicker-next span { 259 | display: block; 260 | position: absolute; 261 | left: 50%; 262 | margin-left: -8px; 263 | top: 50%; 264 | margin-top: -8px; 265 | } 266 | .ui-datepicker .ui-datepicker-title { 267 | margin: 0 2.3em; 268 | line-height: 1.8em; 269 | text-align: center; 270 | } 271 | .ui-datepicker .ui-datepicker-title select { 272 | font-size: 1em; 273 | margin: 1px 0; 274 | } 275 | .ui-datepicker select.ui-datepicker-month, 276 | .ui-datepicker select.ui-datepicker-year { 277 | width: 49%; 278 | } 279 | .ui-datepicker table { 280 | width: 100%; 281 | font-size: .9em; 282 | border-collapse: collapse; 283 | margin: 0 0 .4em; 284 | } 285 | .ui-datepicker th { 286 | padding: .7em .3em; 287 | text-align: center; 288 | font-weight: bold; 289 | border: 0; 290 | } 291 | .ui-datepicker td { 292 | border: 0; 293 | padding: 1px; 294 | } 295 | .ui-datepicker td span, 296 | .ui-datepicker td a { 297 | display: block; 298 | padding: .2em; 299 | text-align: right; 300 | text-decoration: none; 301 | } 302 | .ui-datepicker .ui-datepicker-buttonpane { 303 | background-image: none; 304 | margin: .7em 0 0 0; 305 | padding: 0 .2em; 306 | border-left: 0; 307 | border-right: 0; 308 | border-bottom: 0; 309 | } 310 | .ui-datepicker .ui-datepicker-buttonpane button { 311 | float: right; 312 | margin: .5em .2em .4em; 313 | cursor: pointer; 314 | padding: .2em .6em .3em .6em; 315 | width: auto; 316 | overflow: visible; 317 | } 318 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { 319 | float: left; 320 | } 321 | 322 | /* with multiple calendars */ 323 | .ui-datepicker.ui-datepicker-multi { 324 | width: auto; 325 | } 326 | .ui-datepicker-multi .ui-datepicker-group { 327 | float: left; 328 | } 329 | .ui-datepicker-multi .ui-datepicker-group table { 330 | width: 95%; 331 | margin: 0 auto .4em; 332 | } 333 | .ui-datepicker-multi-2 .ui-datepicker-group { 334 | width: 50%; 335 | } 336 | .ui-datepicker-multi-3 .ui-datepicker-group { 337 | width: 33.3%; 338 | } 339 | .ui-datepicker-multi-4 .ui-datepicker-group { 340 | width: 25%; 341 | } 342 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, 343 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { 344 | border-left-width: 0; 345 | } 346 | .ui-datepicker-multi .ui-datepicker-buttonpane { 347 | clear: left; 348 | } 349 | .ui-datepicker-row-break { 350 | clear: both; 351 | width: 100%; 352 | font-size: 0; 353 | } 354 | 355 | /* RTL support */ 356 | .ui-datepicker-rtl { 357 | direction: rtl; 358 | } 359 | .ui-datepicker-rtl .ui-datepicker-prev { 360 | right: 2px; 361 | left: auto; 362 | } 363 | .ui-datepicker-rtl .ui-datepicker-next { 364 | left: 2px; 365 | right: auto; 366 | } 367 | .ui-datepicker-rtl .ui-datepicker-prev:hover { 368 | right: 1px; 369 | left: auto; 370 | } 371 | .ui-datepicker-rtl .ui-datepicker-next:hover { 372 | left: 1px; 373 | right: auto; 374 | } 375 | .ui-datepicker-rtl .ui-datepicker-buttonpane { 376 | clear: right; 377 | } 378 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { 379 | float: left; 380 | } 381 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, 382 | .ui-datepicker-rtl .ui-datepicker-group { 383 | float: right; 384 | } 385 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, 386 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { 387 | border-right-width: 0; 388 | border-left-width: 1px; 389 | } 390 | .ui-dialog { 391 | overflow: hidden; 392 | position: absolute; 393 | top: 0; 394 | left: 0; 395 | padding: .2em; 396 | outline: 0; 397 | } 398 | .ui-dialog .ui-dialog-titlebar { 399 | padding: .4em 1em; 400 | position: relative; 401 | } 402 | .ui-dialog .ui-dialog-title { 403 | float: left; 404 | margin: .1em 0; 405 | white-space: nowrap; 406 | width: 90%; 407 | overflow: hidden; 408 | text-overflow: ellipsis; 409 | } 410 | .ui-dialog .ui-dialog-titlebar-close { 411 | position: absolute; 412 | right: .3em; 413 | top: 50%; 414 | width: 20px; 415 | margin: -10px 0 0 0; 416 | padding: 1px; 417 | height: 20px; 418 | } 419 | .ui-dialog .ui-dialog-content { 420 | position: relative; 421 | border: 0; 422 | padding: .5em 1em; 423 | background: none; 424 | overflow: auto; 425 | } 426 | .ui-dialog .ui-dialog-buttonpane { 427 | text-align: left; 428 | border-width: 1px 0 0 0; 429 | background-image: none; 430 | margin-top: .5em; 431 | padding: .3em 1em .5em .4em; 432 | } 433 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { 434 | float: right; 435 | } 436 | .ui-dialog .ui-dialog-buttonpane button { 437 | margin: .5em .4em .5em 0; 438 | cursor: pointer; 439 | } 440 | .ui-dialog .ui-resizable-se { 441 | width: 12px; 442 | height: 12px; 443 | right: -5px; 444 | bottom: -5px; 445 | background-position: 16px 16px; 446 | } 447 | .ui-draggable .ui-dialog-titlebar { 448 | cursor: move; 449 | } 450 | .ui-draggable-handle { 451 | -ms-touch-action: none; 452 | touch-action: none; 453 | } 454 | .ui-menu { 455 | list-style: none; 456 | padding: 0; 457 | margin: 0; 458 | display: block; 459 | outline: none; 460 | } 461 | .ui-menu .ui-menu { 462 | position: absolute; 463 | } 464 | .ui-menu .ui-menu-item { 465 | position: relative; 466 | margin: 0; 467 | padding: 3px 1em 3px .4em; 468 | cursor: pointer; 469 | min-height: 0; /* support: IE7 */ 470 | /* support: IE10, see #8844 */ 471 | list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); 472 | } 473 | .ui-menu .ui-menu-divider { 474 | margin: 5px 0; 475 | height: 0; 476 | font-size: 0; 477 | line-height: 0; 478 | border-width: 1px 0 0 0; 479 | } 480 | .ui-menu .ui-state-focus, 481 | .ui-menu .ui-state-active { 482 | margin: -1px; 483 | } 484 | 485 | /* icon support */ 486 | .ui-menu-icons { 487 | position: relative; 488 | } 489 | .ui-menu-icons .ui-menu-item { 490 | padding-left: 2em; 491 | } 492 | 493 | /* left-aligned */ 494 | .ui-menu .ui-icon { 495 | position: absolute; 496 | top: 0; 497 | bottom: 0; 498 | left: .2em; 499 | margin: auto 0; 500 | } 501 | 502 | /* right-aligned */ 503 | .ui-menu .ui-menu-icon { 504 | left: auto; 505 | right: 0; 506 | } 507 | .ui-progressbar { 508 | height: 2em; 509 | text-align: left; 510 | overflow: hidden; 511 | } 512 | .ui-progressbar .ui-progressbar-value { 513 | margin: -1px; 514 | height: 100%; 515 | } 516 | .ui-progressbar .ui-progressbar-overlay { 517 | background: url("images/animated-overlay.gif"); 518 | height: 100%; 519 | filter: alpha(opacity=25); 520 | opacity: 0.25; 521 | } 522 | .ui-progressbar-indeterminate .ui-progressbar-value { 523 | background-image: none; 524 | } 525 | .ui-resizable { 526 | position: relative; 527 | } 528 | .ui-resizable-handle { 529 | position: absolute; 530 | font-size: 0.1px; 531 | display: block; 532 | -ms-touch-action: none; 533 | touch-action: none; 534 | } 535 | .ui-resizable-disabled .ui-resizable-handle, 536 | .ui-resizable-autohide .ui-resizable-handle { 537 | display: none; 538 | } 539 | .ui-resizable-n { 540 | cursor: n-resize; 541 | height: 7px; 542 | width: 100%; 543 | top: -5px; 544 | left: 0; 545 | } 546 | .ui-resizable-s { 547 | cursor: s-resize; 548 | height: 7px; 549 | width: 100%; 550 | bottom: -5px; 551 | left: 0; 552 | } 553 | .ui-resizable-e { 554 | cursor: e-resize; 555 | width: 7px; 556 | right: -5px; 557 | top: 0; 558 | height: 100%; 559 | } 560 | .ui-resizable-w { 561 | cursor: w-resize; 562 | width: 7px; 563 | left: -5px; 564 | top: 0; 565 | height: 100%; 566 | } 567 | .ui-resizable-se { 568 | cursor: se-resize; 569 | width: 12px; 570 | height: 12px; 571 | right: 1px; 572 | bottom: 1px; 573 | } 574 | .ui-resizable-sw { 575 | cursor: sw-resize; 576 | width: 9px; 577 | height: 9px; 578 | left: -5px; 579 | bottom: -5px; 580 | } 581 | .ui-resizable-nw { 582 | cursor: nw-resize; 583 | width: 9px; 584 | height: 9px; 585 | left: -5px; 586 | top: -5px; 587 | } 588 | .ui-resizable-ne { 589 | cursor: ne-resize; 590 | width: 9px; 591 | height: 9px; 592 | right: -5px; 593 | top: -5px; 594 | } 595 | .ui-selectable { 596 | -ms-touch-action: none; 597 | touch-action: none; 598 | } 599 | .ui-selectable-helper { 600 | position: absolute; 601 | z-index: 100; 602 | border: 1px dotted black; 603 | } 604 | .ui-selectmenu-menu { 605 | padding: 0; 606 | margin: 0; 607 | position: absolute; 608 | top: 0; 609 | left: 0; 610 | display: none; 611 | } 612 | .ui-selectmenu-menu .ui-menu { 613 | overflow: auto; 614 | /* Support: IE7 */ 615 | overflow-x: hidden; 616 | padding-bottom: 1px; 617 | } 618 | .ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { 619 | font-size: 1em; 620 | font-weight: bold; 621 | line-height: 1.5; 622 | padding: 2px 0.4em; 623 | margin: 0.5em 0 0 0; 624 | height: auto; 625 | border: 0; 626 | } 627 | .ui-selectmenu-open { 628 | display: block; 629 | } 630 | .ui-selectmenu-button { 631 | display: inline-block; 632 | overflow: hidden; 633 | position: relative; 634 | text-decoration: none; 635 | cursor: pointer; 636 | } 637 | .ui-selectmenu-button span.ui-icon { 638 | right: 0.5em; 639 | left: auto; 640 | margin-top: -8px; 641 | position: absolute; 642 | top: 50%; 643 | } 644 | .ui-selectmenu-button span.ui-selectmenu-text { 645 | text-align: left; 646 | padding: 0.4em 2.1em 0.4em 1em; 647 | display: block; 648 | line-height: 1.4; 649 | overflow: hidden; 650 | text-overflow: ellipsis; 651 | white-space: nowrap; 652 | } 653 | .ui-slider { 654 | position: relative; 655 | text-align: left; 656 | } 657 | .ui-slider .ui-slider-handle { 658 | position: absolute; 659 | z-index: 2; 660 | width: 1.2em; 661 | height: 1.2em; 662 | cursor: default; 663 | -ms-touch-action: none; 664 | touch-action: none; 665 | } 666 | .ui-slider .ui-slider-range { 667 | position: absolute; 668 | z-index: 1; 669 | font-size: .7em; 670 | display: block; 671 | border: 0; 672 | background-position: 0 0; 673 | } 674 | 675 | /* For IE8 - See #6727 */ 676 | .ui-slider.ui-state-disabled .ui-slider-handle, 677 | .ui-slider.ui-state-disabled .ui-slider-range { 678 | filter: inherit; 679 | } 680 | 681 | .ui-slider-horizontal { 682 | height: .8em; 683 | } 684 | .ui-slider-horizontal .ui-slider-handle { 685 | top: -.3em; 686 | margin-left: -.6em; 687 | } 688 | .ui-slider-horizontal .ui-slider-range { 689 | top: 0; 690 | height: 100%; 691 | } 692 | .ui-slider-horizontal .ui-slider-range-min { 693 | left: 0; 694 | } 695 | .ui-slider-horizontal .ui-slider-range-max { 696 | right: 0; 697 | } 698 | 699 | .ui-slider-vertical { 700 | width: .8em; 701 | height: 100px; 702 | } 703 | .ui-slider-vertical .ui-slider-handle { 704 | left: -.3em; 705 | margin-left: 0; 706 | margin-bottom: -.6em; 707 | } 708 | .ui-slider-vertical .ui-slider-range { 709 | left: 0; 710 | width: 100%; 711 | } 712 | .ui-slider-vertical .ui-slider-range-min { 713 | bottom: 0; 714 | } 715 | .ui-slider-vertical .ui-slider-range-max { 716 | top: 0; 717 | } 718 | .ui-sortable-handle { 719 | -ms-touch-action: none; 720 | touch-action: none; 721 | } 722 | .ui-spinner { 723 | position: relative; 724 | display: inline-block; 725 | overflow: hidden; 726 | padding: 0; 727 | vertical-align: middle; 728 | } 729 | .ui-spinner-input { 730 | border: none; 731 | background: none; 732 | color: inherit; 733 | padding: 0; 734 | margin: .2em 0; 735 | vertical-align: middle; 736 | margin-left: .4em; 737 | margin-right: 22px; 738 | } 739 | .ui-spinner-button { 740 | width: 16px; 741 | height: 50%; 742 | font-size: .5em; 743 | padding: 0; 744 | margin: 0; 745 | text-align: center; 746 | position: absolute; 747 | cursor: default; 748 | display: block; 749 | overflow: hidden; 750 | right: 0; 751 | } 752 | /* more specificity required here to override default borders */ 753 | .ui-spinner a.ui-spinner-button { 754 | border-top: none; 755 | border-bottom: none; 756 | border-right: none; 757 | } 758 | /* vertically center icon */ 759 | .ui-spinner .ui-icon { 760 | position: absolute; 761 | margin-top: -8px; 762 | top: 50%; 763 | left: 0; 764 | } 765 | .ui-spinner-up { 766 | top: 0; 767 | } 768 | .ui-spinner-down { 769 | bottom: 0; 770 | } 771 | 772 | /* TR overrides */ 773 | .ui-spinner .ui-icon-triangle-1-s { 774 | /* need to fix icons sprite */ 775 | background-position: -65px -16px; 776 | } 777 | .ui-tabs { 778 | position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ 779 | padding: .2em; 780 | } 781 | .ui-tabs .ui-tabs-nav { 782 | margin: 0; 783 | padding: .2em .2em 0; 784 | } 785 | .ui-tabs .ui-tabs-nav li { 786 | list-style: none; 787 | float: left; 788 | position: relative; 789 | top: 0; 790 | margin: 1px .2em 0 0; 791 | border-bottom-width: 0; 792 | padding: 0; 793 | white-space: nowrap; 794 | } 795 | .ui-tabs .ui-tabs-nav .ui-tabs-anchor { 796 | float: left; 797 | padding: .5em 1em; 798 | text-decoration: none; 799 | } 800 | .ui-tabs .ui-tabs-nav li.ui-tabs-active { 801 | margin-bottom: -1px; 802 | padding-bottom: 1px; 803 | } 804 | .ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, 805 | .ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, 806 | .ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { 807 | cursor: text; 808 | } 809 | .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { 810 | cursor: pointer; 811 | } 812 | .ui-tabs .ui-tabs-panel { 813 | display: block; 814 | border-width: 0; 815 | padding: 1em 1.4em; 816 | background: none; 817 | } 818 | .ui-tooltip { 819 | padding: 8px; 820 | position: absolute; 821 | z-index: 9999; 822 | max-width: 300px; 823 | -webkit-box-shadow: 0 0 5px #aaa; 824 | box-shadow: 0 0 5px #aaa; 825 | } 826 | body .ui-tooltip { 827 | border-width: 2px; 828 | } 829 | 830 | /* Component containers 831 | ----------------------------------*/ 832 | .ui-widget { 833 | font-family: Verdana,Arial,sans-serif; 834 | font-size: 1.1em; 835 | } 836 | .ui-widget .ui-widget { 837 | font-size: 1em; 838 | } 839 | .ui-widget input, 840 | .ui-widget select, 841 | .ui-widget textarea, 842 | .ui-widget button { 843 | font-family: Verdana,Arial,sans-serif; 844 | font-size: 1em; 845 | } 846 | .ui-widget-content { 847 | border: 1px solid #aaaaaa; 848 | background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x; 849 | color: #222222; 850 | } 851 | .ui-widget-content a { 852 | color: #222222; 853 | } 854 | .ui-widget-header { 855 | border: 1px solid #aaaaaa; 856 | background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; 857 | color: #222222; 858 | font-weight: bold; 859 | } 860 | .ui-widget-header a { 861 | color: #222222; 862 | } 863 | 864 | /* Interaction states 865 | ----------------------------------*/ 866 | .ui-state-default, 867 | .ui-widget-content .ui-state-default, 868 | .ui-widget-header .ui-state-default { 869 | border: 1px solid #d3d3d3; 870 | background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; 871 | font-weight: normal; 872 | color: #555555; 873 | } 874 | .ui-state-default a, 875 | .ui-state-default a:link, 876 | .ui-state-default a:visited { 877 | color: #555555; 878 | text-decoration: none; 879 | } 880 | .ui-state-hover, 881 | .ui-widget-content .ui-state-hover, 882 | .ui-widget-header .ui-state-hover, 883 | .ui-state-focus, 884 | .ui-widget-content .ui-state-focus, 885 | .ui-widget-header .ui-state-focus { 886 | border: 1px solid #999999; 887 | background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; 888 | font-weight: normal; 889 | color: #212121; 890 | } 891 | .ui-state-hover a, 892 | .ui-state-hover a:hover, 893 | .ui-state-hover a:link, 894 | .ui-state-hover a:visited, 895 | .ui-state-focus a, 896 | .ui-state-focus a:hover, 897 | .ui-state-focus a:link, 898 | .ui-state-focus a:visited { 899 | color: #212121; 900 | text-decoration: none; 901 | } 902 | .ui-state-active, 903 | .ui-widget-content .ui-state-active, 904 | .ui-widget-header .ui-state-active { 905 | border: 1px solid #aaaaaa; 906 | background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; 907 | font-weight: normal; 908 | color: #212121; 909 | } 910 | .ui-state-active a, 911 | .ui-state-active a:link, 912 | .ui-state-active a:visited { 913 | color: #212121; 914 | text-decoration: none; 915 | } 916 | 917 | /* Interaction Cues 918 | ----------------------------------*/ 919 | .ui-state-highlight, 920 | .ui-widget-content .ui-state-highlight, 921 | .ui-widget-header .ui-state-highlight { 922 | border: 1px solid #fcefa1; 923 | background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; 924 | color: #363636; 925 | } 926 | .ui-state-highlight a, 927 | .ui-widget-content .ui-state-highlight a, 928 | .ui-widget-header .ui-state-highlight a { 929 | color: #363636; 930 | } 931 | .ui-state-error, 932 | .ui-widget-content .ui-state-error, 933 | .ui-widget-header .ui-state-error { 934 | border: 1px solid #cd0a0a; 935 | background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; 936 | color: #cd0a0a; 937 | } 938 | .ui-state-error a, 939 | .ui-widget-content .ui-state-error a, 940 | .ui-widget-header .ui-state-error a { 941 | color: #cd0a0a; 942 | } 943 | .ui-state-error-text, 944 | .ui-widget-content .ui-state-error-text, 945 | .ui-widget-header .ui-state-error-text { 946 | color: #cd0a0a; 947 | } 948 | .ui-priority-primary, 949 | .ui-widget-content .ui-priority-primary, 950 | .ui-widget-header .ui-priority-primary { 951 | font-weight: bold; 952 | } 953 | .ui-priority-secondary, 954 | .ui-widget-content .ui-priority-secondary, 955 | .ui-widget-header .ui-priority-secondary { 956 | opacity: .7; 957 | filter:Alpha(Opacity=70); 958 | font-weight: normal; 959 | } 960 | .ui-state-disabled, 961 | .ui-widget-content .ui-state-disabled, 962 | .ui-widget-header .ui-state-disabled { 963 | opacity: .35; 964 | filter:Alpha(Opacity=35); 965 | background-image: none; 966 | } 967 | .ui-state-disabled .ui-icon { 968 | filter:Alpha(Opacity=35); /* For IE8 - See #6059 */ 969 | } 970 | 971 | /* Icons 972 | ----------------------------------*/ 973 | 974 | /* states and images */ 975 | .ui-icon { 976 | width: 16px; 977 | height: 16px; 978 | } 979 | .ui-icon, 980 | .ui-widget-content .ui-icon { 981 | background-image: url("images/ui-icons_222222_256x240.png"); 982 | } 983 | .ui-widget-header .ui-icon { 984 | background-image: url("images/ui-icons_222222_256x240.png"); 985 | } 986 | .ui-state-default .ui-icon { 987 | background-image: url("images/ui-icons_888888_256x240.png"); 988 | } 989 | .ui-state-hover .ui-icon, 990 | .ui-state-focus .ui-icon { 991 | background-image: url("images/ui-icons_454545_256x240.png"); 992 | } 993 | .ui-state-active .ui-icon { 994 | background-image: url("images/ui-icons_454545_256x240.png"); 995 | } 996 | .ui-state-highlight .ui-icon { 997 | background-image: url("images/ui-icons_2e83ff_256x240.png"); 998 | } 999 | .ui-state-error .ui-icon, 1000 | .ui-state-error-text .ui-icon { 1001 | background-image: url("images/ui-icons_cd0a0a_256x240.png"); 1002 | } 1003 | 1004 | /* positioning */ 1005 | .ui-icon-blank { background-position: 16px 16px; } 1006 | .ui-icon-carat-1-n { background-position: 0 0; } 1007 | .ui-icon-carat-1-ne { background-position: -16px 0; } 1008 | .ui-icon-carat-1-e { background-position: -32px 0; } 1009 | .ui-icon-carat-1-se { background-position: -48px 0; } 1010 | .ui-icon-carat-1-s { background-position: -64px 0; } 1011 | .ui-icon-carat-1-sw { background-position: -80px 0; } 1012 | .ui-icon-carat-1-w { background-position: -96px 0; } 1013 | .ui-icon-carat-1-nw { background-position: -112px 0; } 1014 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 1015 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 1016 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 1017 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 1018 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 1019 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 1020 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 1021 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 1022 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 1023 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 1024 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 1025 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 1026 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 1027 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 1028 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 1029 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 1030 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 1031 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 1032 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 1033 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 1034 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 1035 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 1036 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 1037 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 1038 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 1039 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 1040 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 1041 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 1042 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 1043 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 1044 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 1045 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 1046 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 1047 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 1048 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 1049 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 1050 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 1051 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 1052 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 1053 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 1054 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 1055 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 1056 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 1057 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 1058 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 1059 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 1060 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 1061 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 1062 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 1063 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 1064 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 1065 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 1066 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 1067 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 1068 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 1069 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 1070 | .ui-icon-arrow-4 { background-position: 0 -80px; } 1071 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 1072 | .ui-icon-extlink { background-position: -32px -80px; } 1073 | .ui-icon-newwin { background-position: -48px -80px; } 1074 | .ui-icon-refresh { background-position: -64px -80px; } 1075 | .ui-icon-shuffle { background-position: -80px -80px; } 1076 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 1077 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 1078 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 1079 | .ui-icon-folder-open { background-position: -16px -96px; } 1080 | .ui-icon-document { background-position: -32px -96px; } 1081 | .ui-icon-document-b { background-position: -48px -96px; } 1082 | .ui-icon-note { background-position: -64px -96px; } 1083 | .ui-icon-mail-closed { background-position: -80px -96px; } 1084 | .ui-icon-mail-open { background-position: -96px -96px; } 1085 | .ui-icon-suitcase { background-position: -112px -96px; } 1086 | .ui-icon-comment { background-position: -128px -96px; } 1087 | .ui-icon-person { background-position: -144px -96px; } 1088 | .ui-icon-print { background-position: -160px -96px; } 1089 | .ui-icon-trash { background-position: -176px -96px; } 1090 | .ui-icon-locked { background-position: -192px -96px; } 1091 | .ui-icon-unlocked { background-position: -208px -96px; } 1092 | .ui-icon-bookmark { background-position: -224px -96px; } 1093 | .ui-icon-tag { background-position: -240px -96px; } 1094 | .ui-icon-home { background-position: 0 -112px; } 1095 | .ui-icon-flag { background-position: -16px -112px; } 1096 | .ui-icon-calendar { background-position: -32px -112px; } 1097 | .ui-icon-cart { background-position: -48px -112px; } 1098 | .ui-icon-pencil { background-position: -64px -112px; } 1099 | .ui-icon-clock { background-position: -80px -112px; } 1100 | .ui-icon-disk { background-position: -96px -112px; } 1101 | .ui-icon-calculator { background-position: -112px -112px; } 1102 | .ui-icon-zoomin { background-position: -128px -112px; } 1103 | .ui-icon-zoomout { background-position: -144px -112px; } 1104 | .ui-icon-search { background-position: -160px -112px; } 1105 | .ui-icon-wrench { background-position: -176px -112px; } 1106 | .ui-icon-gear { background-position: -192px -112px; } 1107 | .ui-icon-heart { background-position: -208px -112px; } 1108 | .ui-icon-star { background-position: -224px -112px; } 1109 | .ui-icon-link { background-position: -240px -112px; } 1110 | .ui-icon-cancel { background-position: 0 -128px; } 1111 | .ui-icon-plus { background-position: -16px -128px; } 1112 | .ui-icon-plusthick { background-position: -32px -128px; } 1113 | .ui-icon-minus { background-position: -48px -128px; } 1114 | .ui-icon-minusthick { background-position: -64px -128px; } 1115 | .ui-icon-close { background-position: -80px -128px; } 1116 | .ui-icon-closethick { background-position: -96px -128px; } 1117 | .ui-icon-key { background-position: -112px -128px; } 1118 | .ui-icon-lightbulb { background-position: -128px -128px; } 1119 | .ui-icon-scissors { background-position: -144px -128px; } 1120 | .ui-icon-clipboard { background-position: -160px -128px; } 1121 | .ui-icon-copy { background-position: -176px -128px; } 1122 | .ui-icon-contact { background-position: -192px -128px; } 1123 | .ui-icon-image { background-position: -208px -128px; } 1124 | .ui-icon-video { background-position: -224px -128px; } 1125 | .ui-icon-script { background-position: -240px -128px; } 1126 | .ui-icon-alert { background-position: 0 -144px; } 1127 | .ui-icon-info { background-position: -16px -144px; } 1128 | .ui-icon-notice { background-position: -32px -144px; } 1129 | .ui-icon-help { background-position: -48px -144px; } 1130 | .ui-icon-check { background-position: -64px -144px; } 1131 | .ui-icon-bullet { background-position: -80px -144px; } 1132 | .ui-icon-radio-on { background-position: -96px -144px; } 1133 | .ui-icon-radio-off { background-position: -112px -144px; } 1134 | .ui-icon-pin-w { background-position: -128px -144px; } 1135 | .ui-icon-pin-s { background-position: -144px -144px; } 1136 | .ui-icon-play { background-position: 0 -160px; } 1137 | .ui-icon-pause { background-position: -16px -160px; } 1138 | .ui-icon-seek-next { background-position: -32px -160px; } 1139 | .ui-icon-seek-prev { background-position: -48px -160px; } 1140 | .ui-icon-seek-end { background-position: -64px -160px; } 1141 | .ui-icon-seek-start { background-position: -80px -160px; } 1142 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 1143 | .ui-icon-seek-first { background-position: -80px -160px; } 1144 | .ui-icon-stop { background-position: -96px -160px; } 1145 | .ui-icon-eject { background-position: -112px -160px; } 1146 | .ui-icon-volume-off { background-position: -128px -160px; } 1147 | .ui-icon-volume-on { background-position: -144px -160px; } 1148 | .ui-icon-power { background-position: 0 -176px; } 1149 | .ui-icon-signal-diag { background-position: -16px -176px; } 1150 | .ui-icon-signal { background-position: -32px -176px; } 1151 | .ui-icon-battery-0 { background-position: -48px -176px; } 1152 | .ui-icon-battery-1 { background-position: -64px -176px; } 1153 | .ui-icon-battery-2 { background-position: -80px -176px; } 1154 | .ui-icon-battery-3 { background-position: -96px -176px; } 1155 | .ui-icon-circle-plus { background-position: 0 -192px; } 1156 | .ui-icon-circle-minus { background-position: -16px -192px; } 1157 | .ui-icon-circle-close { background-position: -32px -192px; } 1158 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 1159 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 1160 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 1161 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 1162 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 1163 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 1164 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 1165 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 1166 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 1167 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 1168 | .ui-icon-circle-check { background-position: -208px -192px; } 1169 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 1170 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 1171 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 1172 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 1173 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 1174 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 1175 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 1176 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 1177 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 1178 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 1179 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 1180 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 1181 | 1182 | 1183 | /* Misc visuals 1184 | ----------------------------------*/ 1185 | 1186 | /* Corner radius */ 1187 | .ui-corner-all, 1188 | .ui-corner-top, 1189 | .ui-corner-left, 1190 | .ui-corner-tl { 1191 | border-top-left-radius: 4px; 1192 | } 1193 | .ui-corner-all, 1194 | .ui-corner-top, 1195 | .ui-corner-right, 1196 | .ui-corner-tr { 1197 | border-top-right-radius: 4px; 1198 | } 1199 | .ui-corner-all, 1200 | .ui-corner-bottom, 1201 | .ui-corner-left, 1202 | .ui-corner-bl { 1203 | border-bottom-left-radius: 4px; 1204 | } 1205 | .ui-corner-all, 1206 | .ui-corner-bottom, 1207 | .ui-corner-right, 1208 | .ui-corner-br { 1209 | border-bottom-right-radius: 4px; 1210 | } 1211 | 1212 | /* Overlays */ 1213 | .ui-widget-overlay { 1214 | background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; 1215 | opacity: .3; 1216 | filter: Alpha(Opacity=30); 1217 | } 1218 | .ui-widget-shadow { 1219 | margin: -8px 0 0 -8px; 1220 | padding: 8px; 1221 | background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; 1222 | opacity: .3; 1223 | filter: Alpha(Opacity=30); 1224 | border-radius: 8px; 1225 | } 1226 | -------------------------------------------------------------------------------- /software-license-manager/includes/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arsenal21/software-license-manager/b94b26017c7fa4a55732a06f811407abcf6c1b69/software-license-manager/includes/index.html -------------------------------------------------------------------------------- /software-license-manager/includes/slm-api-listener.php: -------------------------------------------------------------------------------- 1 | log_debug( 'API - Request received from IP: ' . $ip_address . ', Action type: ' . $action_type ); 23 | 24 | //Trigger an action hook 25 | do_action( 'slm_api_listener_init' ); 26 | 27 | //This is an API query for the license manager. Handle the query. 28 | $this->creation_api_listener(); 29 | $this->activation_api_listener(); 30 | $this->deactivation_api_listener(); 31 | $this->check_api_listener(); 32 | } 33 | } 34 | 35 | function creation_api_listener() { 36 | if ( isset( $_REQUEST['slm_action'] ) && trim( $_REQUEST['slm_action'] ) == 'slm_create_new' ) { 37 | //Handle the licene creation API query 38 | global $slm_debug_logger; 39 | 40 | $options = get_option( 'slm_plugin_options' ); 41 | $lic_key_prefix = $options['lic_prefix']; 42 | 43 | SLM_API_Utility::verify_secret_key_for_creation(); //Verify the secret key first. 44 | 45 | $slm_debug_logger->log_debug( 'API - license creation (slm_create_new) request received.' ); 46 | 47 | //Action hook 48 | do_action( 'slm_api_listener_slm_create_new' ); 49 | 50 | $fields = array(); 51 | if ( isset( $_REQUEST['license_key'] ) && ! empty( $_REQUEST['license_key'] ) ) { 52 | $fields['license_key'] = SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['license_key'] );//Use the key you pass via the request 53 | } else { 54 | $fields['license_key'] = uniqid( $lic_key_prefix );//Use random generated key 55 | } 56 | $fields['lic_status'] = isset( $_REQUEST['lic_status'] ) ? wp_unslash( SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['lic_status'] ) ) : 'pending'; 57 | $fields['first_name'] = wp_unslash( SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['first_name'] ) ); 58 | $fields['last_name'] = wp_unslash( SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['last_name'] ) ); 59 | $fields['email'] = sanitize_email( $_REQUEST['email'] ); 60 | $fields['company_name'] = isset( $_REQUEST['company_name'] ) ? wp_unslash( SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['company_name'] ) ) : ''; 61 | $fields['txn_id'] = SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['txn_id'] ); 62 | if ( empty( $_REQUEST['max_allowed_domains'] ) ) { 63 | $fields['max_allowed_domains'] = $options['default_max_domains']; 64 | } else { 65 | $fields['max_allowed_domains'] = intval( $_REQUEST['max_allowed_domains'] ); 66 | } 67 | $fields['date_created'] = isset( $_REQUEST['date_created'] ) ? sanitize_text_field( $_REQUEST['date_created'] ) : date( 'Y-m-d' ); 68 | $fields['date_expiry'] = isset( $_REQUEST['date_expiry'] ) ? sanitize_text_field( $_REQUEST['date_expiry'] ) : ''; 69 | $fields['product_ref'] = isset( $_REQUEST['product_ref'] ) ? wp_unslash( SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['product_ref'] ) ) : ''; 70 | $fields['subscr_id'] = isset( $_REQUEST['subscr_id'] ) ? wp_unslash( SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['subscr_id'] ) ) : ''; 71 | $fields['user_ref'] = isset( $_REQUEST['user_ref'] ) ? wp_unslash( SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['user_ref'] ) ) : ''; 72 | 73 | global $wpdb; 74 | $tbl_name = SLM_TBL_LICENSE_KEYS; 75 | $result = $wpdb->insert( $tbl_name, $fields ); 76 | if ( $result === false ) { 77 | //error inserting 78 | $args = ( array( 79 | 'result' => 'error', 80 | 'message' => 'License creation failed', 81 | 'error_code' => SLM_Error_Codes::CREATE_FAILED, 82 | ) ); 83 | SLM_API_Utility::output_api_response( $args ); 84 | } else { 85 | $args = ( array( 86 | 'result' => 'success', 87 | 'message' => 'License successfully created', 88 | 'key' => $fields['license_key'], 89 | ) ); 90 | SLM_API_Utility::output_api_response( $args ); 91 | } 92 | } 93 | } 94 | 95 | /* 96 | * Query Parameters 97 | * 1) slm_action = slm_create_new 98 | * 2) secret_key 99 | * 3) license_key 100 | * 4) registered_domain (optional) 101 | */ 102 | 103 | function activation_api_listener() { 104 | if ( isset( $_REQUEST['slm_action'] ) && trim( $_REQUEST['slm_action'] ) == 'slm_activate' ) { 105 | //Handle the license activation API query 106 | global $slm_debug_logger; 107 | 108 | SLM_API_Utility::verify_secret_key(); //Verify the secret key first. 109 | 110 | $slm_debug_logger->log_debug( 'API - license activation (slm_activate) request received.' ); 111 | 112 | //Action hook 113 | do_action( 'slm_api_listener_slm_activate' ); 114 | 115 | $fields = array(); 116 | $fields['lic_key'] = SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['license_key'] ); 117 | $fields['registered_domain'] = isset($_REQUEST['registered_domain']) ? trim( wp_unslash( sanitize_text_field( $_REQUEST['registered_domain'] ) ) ) : ''; 118 | $fields['item_reference'] = isset($_REQUEST['item_reference']) ? trim( sanitize_text_field( $_REQUEST['item_reference'] ) ) : ''; 119 | $slm_debug_logger->log_debug( 'License key: ' . $fields['lic_key'] . ' Domain: ' . $fields['registered_domain'] ); 120 | 121 | global $wpdb; 122 | $tbl_name = SLM_TBL_LICENSE_KEYS; 123 | $reg_table = SLM_TBL_LIC_DOMAIN; 124 | $key = $fields['lic_key']; 125 | $sql_prep1 = $wpdb->prepare( "SELECT * FROM $tbl_name WHERE license_key = %s", $key ); 126 | $retLic = $wpdb->get_row( $sql_prep1, OBJECT ); 127 | 128 | $sql_prep2 = $wpdb->prepare( "SELECT * FROM $reg_table WHERE lic_key = %s", $key ); 129 | $reg_domains = $wpdb->get_results( $sql_prep2, OBJECT ); 130 | if ( $retLic ) { 131 | if ( $retLic->lic_status == 'blocked' ) { 132 | //Trigger action hook 133 | do_action( 'slm_api_listener_slm_activate_key_blocked', $key ); 134 | 135 | $args = ( array( 136 | 'result' => 'error', 137 | 'message' => 'Your License key is blocked', 138 | 'error_code' => SLM_Error_Codes::LICENSE_BLOCKED, 139 | ) ); 140 | SLM_API_Utility::output_api_response( $args ); 141 | } elseif ( $retLic->lic_status == 'expired' ) { 142 | //Trigger action hook 143 | do_action( 'slm_api_listener_slm_activate_key_expired', $key ); 144 | 145 | $args = ( array( 146 | 'result' => 'error', 147 | 'message' => 'Your License key has expired', 148 | 'error_code' => SLM_Error_Codes::LICENSE_EXPIRED, 149 | ) ); 150 | SLM_API_Utility::output_api_response( $args ); 151 | } 152 | 153 | if ( count( $reg_domains ) < floor( $retLic->max_allowed_domains ) ) { 154 | foreach ( $reg_domains as $reg_domain ) { 155 | if ( isset( $_REQUEST['migrate_from'] ) && ( trim( $_REQUEST['migrate_from'] ) == $reg_domain->registered_domain ) ) { 156 | $wpdb->update( $reg_table, array( 'registered_domain' => $fields['registered_domain'] ), array( 'registered_domain' => trim( sanitize_text_field( $_REQUEST['migrate_from'] ) ) ) ); 157 | $args = ( array( 158 | 'result' => 'success', 159 | 'message' => 'Registered domain has been updated', 160 | ) ); 161 | SLM_API_Utility::output_api_response( $args ); 162 | } 163 | if ( $fields['registered_domain'] == $reg_domain->registered_domain ) { 164 | $args = ( array( 165 | 'result' => 'error', 166 | 'message' => 'License key already in use on ' . $reg_domain->registered_domain, 167 | 'error_code' => SLM_Error_Codes::LICENSE_IN_USE, 168 | ) ); 169 | SLM_API_Utility::output_api_response( $args ); 170 | } 171 | } 172 | $fields['lic_key_id'] = $retLic->id; 173 | $wpdb->insert( $reg_table, $fields ); 174 | 175 | $slm_debug_logger->log_debug( 'Updating license key status to active.' ); 176 | $data = array( 'lic_status' => 'active' ); 177 | $where = array( 'id' => $retLic->id ); 178 | $updated = $wpdb->update( $tbl_name, $data, $where ); 179 | 180 | $args = ( array( 181 | 'result' => 'success', 182 | 'message' => 'License key activated', 183 | ) ); 184 | SLM_API_Utility::output_api_response( $args ); 185 | } else { 186 | 187 | //Lets loop through the domains to see if it is being used on an existing domain or not. 188 | foreach ( $reg_domains as $reg_domain ) { 189 | if ( $fields['registered_domain'] == $reg_domain->registered_domain ) { 190 | //Not used on an existing domain. Return error: LICENSE_IN_USE_ON_DOMAIN_AND_MAX_REACHED 191 | $args = ( array( 192 | 'result' => 'error', 193 | 'message' => 'Reached maximum activation. License key already in use on ' . $reg_domain->registered_domain, 194 | 'error_code' => SLM_Error_Codes::LICENSE_IN_USE_ON_DOMAIN_AND_MAX_REACHED, 195 | ) ); 196 | SLM_API_Utility::output_api_response( $args ); 197 | } 198 | } 199 | 200 | //Not used on an existing domain. Return error: REACHED_MAX_DOMAINS 201 | $args = ( array( 202 | 'result' => 'error', 203 | 'message' => 'Reached maximum allowable domains', 204 | 'error_code' => SLM_Error_Codes::REACHED_MAX_DOMAINS, 205 | ) ); 206 | SLM_API_Utility::output_api_response( $args ); 207 | } 208 | } else { 209 | $args = ( array( 210 | 'result' => 'error', 211 | 'message' => 'Invalid license key', 212 | 'error_code' => SLM_Error_Codes::LICENSE_INVALID, 213 | ) ); 214 | SLM_API_Utility::output_api_response( $args ); 215 | } 216 | } 217 | } 218 | 219 | function deactivation_api_listener() { 220 | if ( isset( $_REQUEST['slm_action'] ) && trim( $_REQUEST['slm_action'] ) == 'slm_deactivate' ) { 221 | //Handle the license deactivation API query 222 | global $slm_debug_logger; 223 | 224 | SLM_API_Utility::verify_secret_key(); //Verify the secret key first. 225 | 226 | $slm_debug_logger->log_debug( 'API - license deactivation (slm_deactivate) request received.' ); 227 | 228 | //Action hook 229 | do_action( 'slm_api_listener_slm_deactivate' ); 230 | 231 | if ( empty( $_REQUEST['registered_domain'] ) ) { 232 | $args = ( array( 233 | 'result' => 'error', 234 | 'message' => 'Registered domain information is missing', 235 | 'error_code' => SLM_Error_Codes::DOMAIN_MISSING, 236 | ) ); 237 | SLM_API_Utility::output_api_response( $args ); 238 | } 239 | $registered_domain = trim( wp_unslash( sanitize_text_field( $_REQUEST['registered_domain'] ) ) ); 240 | $license_key = SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['license_key'] ); 241 | $slm_debug_logger->log_debug( 'License key: ' . $license_key . ' Domain: ' . $registered_domain ); 242 | 243 | global $wpdb; 244 | $registered_dom_table = SLM_TBL_LIC_DOMAIN; 245 | $sql_prep = $wpdb->prepare( "DELETE FROM $registered_dom_table WHERE lic_key=%s AND registered_domain=%s", $license_key, $registered_domain ); 246 | $delete = $wpdb->query( $sql_prep ); 247 | if ( $delete === false ) { 248 | $slm_debug_logger->log_debug( 'Error - failed to delete the registered domain from the database.' ); 249 | } elseif ( $delete == 0 ) { 250 | $args = ( array( 251 | 'result' => 'error', 252 | 'message' => 'The license key on this domain is already inactive', 253 | 'error_code' => SLM_Error_Codes::DOMAIN_ALREADY_INACTIVE, 254 | ) ); 255 | SLM_API_Utility::output_api_response( $args ); 256 | } else { 257 | $args = ( array( 258 | 'result' => 'success', 259 | 'message' => 'The license key has been deactivated for this domain', 260 | ) ); 261 | SLM_API_Utility::output_api_response( $args ); 262 | } 263 | } 264 | } 265 | 266 | function check_api_listener() { 267 | if ( isset( $_REQUEST['slm_action'] ) && trim( $_REQUEST['slm_action'] ) == 'slm_check' ) { 268 | //Handle the license check API query 269 | global $slm_debug_logger; 270 | 271 | SLM_API_Utility::verify_secret_key(); //Verify the secret key first. 272 | 273 | $slm_debug_logger->log_debug( 'API - license check (slm_check) request received.' ); 274 | 275 | $fields = array(); 276 | $fields['lic_key'] = SLM_Utility::sanitize_strip_trim_slm_text( $_REQUEST['license_key'] ); 277 | $slm_debug_logger->log_debug( 'License key: ' . $fields['lic_key'] ); 278 | 279 | //Action hook 280 | do_action( 'slm_api_listener_slm_check' ); 281 | 282 | global $wpdb; 283 | $tbl_name = SLM_TBL_LICENSE_KEYS; 284 | $reg_table = SLM_TBL_LIC_DOMAIN; 285 | $key = $fields['lic_key']; 286 | $sql_prep1 = $wpdb->prepare( "SELECT * FROM $tbl_name WHERE license_key = %s", $key ); 287 | $retLic = $wpdb->get_row( $sql_prep1, OBJECT ); 288 | 289 | $sql_prep2 = $wpdb->prepare( "SELECT * FROM $reg_table WHERE lic_key = %s", $key ); 290 | $reg_domains = $wpdb->get_results( $sql_prep2, OBJECT ); 291 | if ( $retLic ) {//A license key exists 292 | $args = apply_filters( 293 | 'slm_check_response_args', 294 | array( 295 | 'result' => 'success', 296 | 'message' => 'License key details retrieved.', 297 | 'license_key' => $retLic->license_key, 298 | 'status' => $retLic->lic_status, 299 | 'max_allowed_domains' => $retLic->max_allowed_domains, 300 | 'email' => $retLic->email, 301 | 'registered_domains' => $reg_domains, 302 | 'date_created' => $retLic->date_created, 303 | 'date_renewed' => $retLic->date_renewed, 304 | 'date_expiry' => $retLic->date_expiry, 305 | 'date' => date("Y-m-d"), 306 | 'product_ref' => $retLic->product_ref, 307 | 'first_name' => $retLic->first_name, 308 | 'last_name' => $retLic->last_name, 309 | 'company_name' => $retLic->company_name, 310 | 'txn_id' => $retLic->txn_id, 311 | 'subscr_id' => $retLic->subscr_id, 312 | ) 313 | ); 314 | //Output the license details 315 | SLM_API_Utility::output_api_response( $args ); 316 | } else { 317 | $args = ( array( 318 | 'result' => 'error', 319 | 'message' => 'Invalid license key', 320 | 'error_code' => SLM_Error_Codes::LICENSE_INVALID, 321 | ) ); 322 | SLM_API_Utility::output_api_response( $args ); 323 | } 324 | } 325 | } 326 | 327 | } 328 | -------------------------------------------------------------------------------- /software-license-manager/includes/slm-api-utility.php: -------------------------------------------------------------------------------- 1 | log_debug( 'API Response - Result: ' . $args['result'] . ' Message: ' . $args['message'] ); 14 | 15 | $args = apply_filters( 'slm_ap_response_args', $args );//TODO - delete this (has a typo). Use the following filter instead. 16 | $args = apply_filters( 'slm_api_response_args', $args ); 17 | 18 | //Send response 19 | header( 'Content-Type: application/json' ); 20 | echo json_encode( $args ); 21 | exit( 0 ); 22 | } 23 | 24 | static function verify_secret_key() { 25 | $slm_options = get_option( 'slm_plugin_options' ); 26 | $right_secret_key = $slm_options['lic_verification_secret']; 27 | $received_secret_key = sanitize_text_field( $_REQUEST['secret_key'] ); 28 | if ( $received_secret_key != $right_secret_key ) { 29 | $args = ( array( 30 | 'result' => 'error', 31 | 'message' => 'Verification API secret key is invalid', 32 | 'error_code' => SLM_Error_Codes::VERIFY_KEY_INVALID, 33 | ) ); 34 | self::output_api_response( $args ); 35 | } 36 | } 37 | 38 | static function verify_secret_key_for_creation() { 39 | $slm_options = get_option( 'slm_plugin_options' ); 40 | $right_secret_key = $slm_options['lic_creation_secret']; 41 | $received_secret_key = sanitize_text_field( $_REQUEST['secret_key'] ); 42 | if ( $received_secret_key != $right_secret_key ) { 43 | $args = ( array( 44 | 'result' => 'error', 45 | 'message' => 'License Creation API secret key is invalid', 46 | 'error_code' => SLM_Error_Codes::CREATE_KEY_INVALID, 47 | ) ); 48 | self::output_api_response( $args ); 49 | } 50 | } 51 | 52 | static function insert_license_data_internal( $fields ) { 53 | /* The fields array should have values for the following keys 54 | //$fields['license_key'] 55 | //$fields['lic_status'] 56 | //$fields['first_name'] 57 | //$fields['last_name'] 58 | //$fields['email'] 59 | //$fields['company_name'] 60 | //$fields['txn_id'] 61 | //$fields['max_allowed_domains'] 62 | */ 63 | global $wpdb; 64 | $tbl_name = SLM_TBL_LICENSE_KEYS; 65 | $fields = array_filter( $fields );//Remove any null values. 66 | $result = $wpdb->insert( $tbl_name, $fields ); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /software-license-manager/includes/slm-debug-logger.php: -------------------------------------------------------------------------------- 1 | log_debug("Some debug message"); 8 | * 9 | * OR 10 | * 11 | * SLM_Debug_Logger::log_debug_st("Some debug message"); 12 | */ 13 | 14 | class SLM_Debug_Logger { 15 | 16 | protected static $instance; 17 | protected $log_folder_path; 18 | protected $default_log_file = 'log.txt'; 19 | protected $overwrite = false; 20 | var $default_log_file_cron = 'log-cron-job.txt'; 21 | var $debug_enabled = false; 22 | var $debug_status = array( 'SUCCESS', 'STATUS', 'NOTICE', 'WARNING', 'FAILURE', 'CRITICAL' ); 23 | var $section_break_marker = "\n----------------------------------------------------------\n\n"; 24 | var $log_reset_marker = "-------- Log File Reset --------\n"; 25 | 26 | function __construct() { 27 | self::$instance = $this; 28 | $this->log_folder_path = WP_LICENSE_MANAGER_PATH . '/logs'; 29 | //Check config and if debug is enabled then set the enabled flag to true 30 | $options = get_option( 'slm_plugin_options' ); 31 | if ( ! empty( $options['enable_debug'] ) ) {//Debugging is enabled 32 | $this->debug_enabled = true; 33 | } 34 | $this->init_default_log_file(); 35 | } 36 | 37 | public static function get_instance() { 38 | return empty( self::$instance ) ? new self() : self::$instance; 39 | } 40 | 41 | function init_default_log_file() { 42 | $options = get_option( 'slm_plugin_options' ); 43 | if ( empty( $options['default_log_file'] ) ) { 44 | $this->default_log_file = uniqid() . '-log.txt'; 45 | $options['default_log_file'] = $this->default_log_file; 46 | update_option( 'slm_plugin_options', $options ); 47 | $this->reset_log_file(); 48 | } else { 49 | $this->default_log_file = $options['default_log_file']; 50 | } 51 | } 52 | 53 | 54 | function get_debug_timestamp() { 55 | return '[' . date( 'm/d/Y g:i A' ) . '] - '; 56 | } 57 | 58 | function get_debug_status( $level ) { 59 | $size = count( $this->debug_status ); 60 | if ( $level >= $size ) { 61 | return 'UNKNOWN'; 62 | } else { 63 | return $this->debug_status[ $level ]; 64 | } 65 | } 66 | 67 | function view_log( $file_name = '' ) { 68 | if ( empty( $file_name ) ) { 69 | $file_name = $this->default_log_file; 70 | } 71 | $log_file = $this->log_folder_path . '/' . $file_name; 72 | if ( ! file_exists( $log_file ) ) { 73 | echo 'Log file is empty'; 74 | exit(); 75 | } 76 | $logfile = fopen( $log_file, 'rb' ); 77 | if ( ! $logfile ) { 78 | wp_die( 'Can\'t open log file.' ); 79 | } 80 | header( 'Content-Type: text/plain' ); 81 | fpassthru( $logfile ); 82 | exit(); 83 | } 84 | 85 | function get_section_break( $section_break ) { 86 | if ( $section_break ) { 87 | return $this->section_break_marker; 88 | } 89 | return ''; 90 | } 91 | 92 | function reset_log_file( $file_name = '' ) { 93 | if ( empty( $file_name ) ) { 94 | $file_name = $this->default_log_file; 95 | } 96 | $content = $this->get_debug_timestamp() . $this->log_reset_marker; 97 | 98 | $this->overwrite = true; 99 | $this->append_to_file( $content, $file_name ); 100 | } 101 | 102 | function append_to_file( $content, $file_name ) { 103 | if ( empty( $file_name ) ) { 104 | $file_name = $this->default_log_file; 105 | } 106 | $debug_log_file = $this->log_folder_path . '/' . $file_name; 107 | $f_opts = $this->overwrite ? 'w' : 'a'; 108 | $fp = fopen( $debug_log_file, $f_opts ); 109 | fwrite( $fp, $content ); 110 | fclose( $fp ); 111 | } 112 | 113 | function log_debug( $message, $level = 0, $section_break = false, $file_name = '' ) { 114 | if ( ! $this->debug_enabled ) { 115 | return; 116 | } 117 | $content = $this->get_debug_timestamp();//Timestamp 118 | $content .= $this->get_debug_status( $level );//Debug status 119 | $content .= ' : '; 120 | $content .= $message . "\n"; 121 | $content .= $this->get_section_break( $section_break ); 122 | $this->append_to_file( $content, $file_name ); 123 | } 124 | 125 | function log_debug_cron( $message, $level = 0, $section_break = false ) { 126 | if ( ! $this->debug_enabled ) { 127 | return; 128 | } 129 | $content = $this->get_debug_timestamp();//Timestamp 130 | $content .= $this->get_debug_status( $level );//Debug status 131 | $content .= ' : '; 132 | $content .= $message . "\n"; 133 | $content .= $this->get_section_break( $section_break ); 134 | //$file_name = $this->default_log_file_cron; 135 | $this->append_to_file( $content, $this->default_log_file_cron ); 136 | } 137 | 138 | static function log_debug_st( $message, $level = 0, $section_break = false, $file_name = '' ) { 139 | $options = get_option( 'slm_plugin_options' ); 140 | if ( empty( $options['enable_debug'] ) ) {//Debugging is disabled 141 | return; 142 | } 143 | self::get_instance(); 144 | $content = '[' . date( 'm/d/Y g:i A' ) . '] - STATUS : ' . $message . "\n"; 145 | $debug_log_file = self::get_instance()->log_folder_path . '/' . self::get_instance()->default_log_file; 146 | $fp = fopen( $debug_log_file, 'a' ); 147 | fwrite( $fp, $content ); 148 | fclose( $fp ); 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /software-license-manager/includes/slm-error-codes.php: -------------------------------------------------------------------------------- 1 | load_scripts(); 7 | 8 | //Add other init time operations here 9 | add_action( 'slm_daily_cron_event', array( &$this, 'slm_daily_cron_event_handler' ) ); 10 | 11 | //View debug log 12 | if ( ! empty( $_REQUEST['slm_view_log'] ) ) { 13 | check_admin_referer( 'slm_view_debug_log', 'slm_view_debug_log_nonce' ); 14 | SLM_Debug_Logger::get_instance()->view_log(); 15 | } 16 | } 17 | 18 | function load_scripts() { 19 | //Load any common scripts and styles only 20 | 21 | //Load all admin side scripts and styles only 22 | if ( is_admin() ) { 23 | wp_enqueue_script( 'jquery' ); 24 | 25 | wp_enqueue_script( 'jquery-ui-datepicker' ); 26 | wp_enqueue_script( 'wplm-custom-admin-js', WP_LICENSE_MANAGER_URL . '/js/wplm-custom-admin.js', array( 'jquery-ui-dialog' ) );//admin only custom js code 27 | 28 | if ( isset( $_GET['page'] ) && $_GET['page'] == 'wp_lic_mgr_addedit' ) {//Only include if we are in the license add/edit interface 29 | wp_enqueue_style( 'jquery-ui-style', WP_LICENSE_MANAGER_URL . '/css/jquery-ui.css' ); 30 | } 31 | //wp_enqueue_style('dialogStylesheet', includes_url().'css/jquery-ui-dialog.css'); 32 | } 33 | } 34 | 35 | function slm_daily_cron_event_handler() { 36 | $options = get_option( 'slm_plugin_options' ); 37 | 38 | do_action( 'slm_daily_cron_event_triggered' ); 39 | 40 | if ( isset( $options['enable_auto_key_expiry'] ) && $options['enable_auto_key_expiry'] == '1' ) { 41 | //Do the auto key expiry task 42 | SLM_Debug_Logger::log_debug_st( 'SLM daily cronjob - auto expiry of license key is enabled.' ); 43 | SLM_Utility::do_auto_key_expiry(); 44 | } 45 | 46 | //Do any ohter daily cronjob tasks. 47 | 48 | } 49 | 50 | }//End of class 51 | -------------------------------------------------------------------------------- /software-license-manager/includes/slm-third-party-integration.php: -------------------------------------------------------------------------------- 1 | log_debug( 'WP eStore integration - checking if a license key needs to be created for this transaction.' ); 12 | $products_table_name = $wpdb->prefix . 'wp_eStore_tbl'; 13 | $slm_data = ''; 14 | 15 | //Check if this is a recurring payment. 16 | if ( function_exists( 'is_paypal_recurring_payment' ) ) { 17 | $recurring_payment = is_paypal_recurring_payment( $payment_data ); 18 | if ( $recurring_payment ) { 19 | $slm_debug_logger->log_debug( 'This is a recurring payment. No need to create a new license key.' ); 20 | do_action( 'slm_estore_recurring_payment_received', $payment_data, $cart_items ); 21 | return $body; 22 | } 23 | } 24 | 25 | foreach ( $cart_items as $current_cart_item ) { 26 | $prod_id = $current_cart_item['item_number']; 27 | $item_name = $current_cart_item['item_name']; 28 | $quantity = $current_cart_item['quantity']; 29 | if ( empty( $quantity ) ) { 30 | $quantity = 1; 31 | } 32 | $slm_debug_logger->log_debug( 'License Manager - Item Number: ' . $prod_id . ', Quantity: ' . $quantity . ', Item Name: ' . $item_name ); 33 | 34 | $retrieved_product = $wpdb->get_row( "SELECT * FROM $products_table_name WHERE id = '$prod_id'", OBJECT ); 35 | $package_product = eStore_is_package_product( $retrieved_product ); 36 | if ( $package_product ) { 37 | $slm_debug_logger->log_debug( 'Checking license key generation for package/bundle product.' ); 38 | $product_ids = explode( ',', $retrieved_product->product_download_url ); 39 | foreach ( $product_ids as $id ) { 40 | $id = trim( $id ); 41 | $retrieved_product_for_specific_id = $wpdb->get_row( "SELECT * FROM $products_table_name WHERE id = '$id'", OBJECT ); 42 | //$slm_data .= slm_estore_check_and_generate_key($retrieved_product_for_specific_id, $payment_data, $cart_items, $item_name); 43 | $slm_data .= slm_estore_check_and_create_key_for_qty( $retrieved_product_for_specific_id, $payment_data, $cart_items, $item_name, $quantity ); 44 | } 45 | } else { 46 | $slm_debug_logger->log_debug( 'Checking license key generation for single item product.' ); 47 | $slm_data .= slm_estore_check_and_create_key_for_qty( $retrieved_product, $payment_data, $cart_items, $item_name, $quantity ); 48 | } 49 | } 50 | 51 | $body = str_replace( '{slm_data}', $slm_data, $body ); 52 | return $body; 53 | } 54 | 55 | function slm_estore_check_and_create_key_for_qty( $retrieved_product, $payment_data, $cart_items, $item_name, $quantity ) { 56 | $prod_key_data = ''; 57 | for ( $i = 0; $i < $quantity; $i++ ) { 58 | $prod_key_data .= slm_estore_check_and_generate_key( $retrieved_product, $payment_data, $cart_items, $item_name ); 59 | } 60 | return $prod_key_data; 61 | } 62 | 63 | function slm_estore_check_and_generate_key( $retrieved_product, $payment_data, $cart_items, $item_name ) { 64 | global $slm_debug_logger; 65 | $license_data = ''; 66 | 67 | if ( $retrieved_product->create_license == 1 ) { 68 | $slm_debug_logger->log_debug( 'Need to create a license key for this product (' . $retrieved_product->id . ')' ); 69 | $slm_key = slm_estore_create_license( $retrieved_product, $payment_data, $cart_items, $item_name ); 70 | $license_data = "\n" . __( 'Item Name: ', 'slm' ) . $retrieved_product->name . ' - ' . __( 'License Key: ', 'slm' ) . $slm_key; 71 | $slm_debug_logger->log_debug( 'Liense data: ' . $license_data ); 72 | $license_data = apply_filters( 'slm_estore_item_license_data', $license_data ); 73 | } 74 | return $license_data; 75 | } 76 | 77 | function slm_estore_create_license( $retrieved_product, $payment_data, $cart_items, $item_name ) { 78 | global $slm_debug_logger; 79 | global $wpdb; 80 | $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME; 81 | 82 | //Retrieve the default settings values. 83 | $options = get_option( 'slm_plugin_options' ); 84 | $lic_key_prefix = $options['lic_prefix']; 85 | $max_domains = $options['default_max_domains']; 86 | 87 | //Lets check any product specific configuration. 88 | $prod_id = $retrieved_product->id; 89 | $product_meta = $wpdb->get_row( "SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_max_allowed_domains'", OBJECT ); 90 | if ( $product_meta ) { 91 | //Found product specific SLM config data. 92 | $max_domains = $product_meta->meta_value; 93 | } else { 94 | //Use the default value from settings (the $max_domains variable contains the default value already). 95 | } 96 | 97 | //Use the default value (1 year from today). If a product specific one is set, it will be overriden later. 98 | $current_date_plus_1year = date( 'Y-m-d', strtotime( '+1 year' ) ); 99 | $slm_date_of_expiry = $current_date_plus_1year; 100 | 101 | //Lets check if any product specific expiry date is set 102 | $product_meta = $wpdb->get_row( "SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_date_of_expiry'", OBJECT ); 103 | if ( $product_meta ) { 104 | //Found product specific SLM config data. Override the expiry date using the product specific configuration. 105 | $num_days_before_expiry = $product_meta->meta_value; 106 | $slm_date_of_expiry = date( 'Y-m-d', strtotime( '+' . $num_days_before_expiry . ' days' ) ); 107 | } 108 | 109 | //Get emember ID from custom fields (if available) 110 | $customvariables = isset($payment_data['custom']) ? eStore_get_payment_custom_var($payment_data['custom']) : array(); 111 | $emember_id = isset($customvariables['eMember_id']) ? $customvariables['eMember_id'] : ''; 112 | 113 | //Create the fields array 114 | $fields = array(); 115 | $fields['license_key'] = uniqid( $lic_key_prefix ); 116 | $fields['lic_status'] = 'pending'; 117 | $fields['first_name'] = $payment_data['first_name']; 118 | $fields['last_name'] = $payment_data['last_name']; 119 | $fields['email'] = $payment_data['payer_email']; 120 | $fields['company_name'] = $payment_data['company_name']; 121 | $fields['txn_id'] = $payment_data['txn_id']; 122 | $fields['max_allowed_domains'] = $max_domains; 123 | $fields['date_created'] = date( 'Y-m-d' ); //Today's date 124 | $fields['date_expiry'] = $slm_date_of_expiry; 125 | $fields['product_ref'] = $prod_id;//WP eStore product ID 126 | $fields['subscr_id'] = isset( $payment_data['subscr_id'] ) ? $payment_data['subscr_id'] : ''; 127 | $fields['user_ref'] = $emember_id;//WP eMember member ID (if available) 128 | 129 | $slm_debug_logger->log_debug( 'Inserting license data into the license manager DB table.' ); 130 | $fields = array_filter( $fields ); //Remove any null values. 131 | 132 | $tbl_name = SLM_TBL_LICENSE_KEYS; 133 | $result = $wpdb->insert( $tbl_name, $fields ); 134 | if ( ! $result ) { 135 | $slm_debug_logger->log_debug( 'Notice! initial database table insert failed on license key table (User Email: ' . $fields['email'] . '). Trying again by converting charset', true ); 136 | //Convert the default PayPal IPN charset to UTF-8 format 137 | $first_name = mb_convert_encoding( $fields['first_name'], 'UTF-8', 'windows-1252' ); 138 | $fields['first_name'] = esc_sql( $first_name ); 139 | $last_name = mb_convert_encoding( $fields['last_name'], 'UTF-8', 'windows-1252' ); 140 | $fields['last_name'] = esc_sql( $last_name ); 141 | $company_name = mb_convert_encoding( $fields['company_name'], 'UTF-8', 'windows-1252' ); 142 | $fields['company_name'] = esc_sql( $company_name ); 143 | 144 | $result = $wpdb->insert( $tbl_name, $fields ); 145 | if ( ! $result ) { 146 | $slm_debug_logger->log_debug( 'Error! Failed to update license key table. DB insert query failed.', false ); 147 | } 148 | } 149 | //SLM_API_Utility::insert_license_data_internal($fields); 150 | 151 | $prod_args = array( 152 | 'estore_prod_id' => $prod_id, 153 | 'estore_item_name' => $item_name, 154 | ); 155 | do_action( 'slm_estore_license_created', $prod_args, $payment_data, $cart_items, $fields ); 156 | 157 | return $fields['license_key']; 158 | } 159 | 160 | /* Code to handle the eStore's product add/edit interface for SLM specific product configuration */ 161 | add_filter( 'eStore_addon_product_settings_filter', 'slm_estore_product_configuration_html', 10, 2 ); //Render the product add/edit HTML 162 | add_action( 'eStore_new_product_added', 'slm_estore_new_product_added', 10, 2 ); //Handle the DB insert after a product add. 163 | add_action( 'eStore_product_updated', 'slm_estore_product_updated', 10, 2 ); //Handle the DB update after a product edit. 164 | add_action( 'eStore_product_deleted', 'slm_estore_product_deleted' ); //Handle the DB delete after a product delete. 165 | 166 | function slm_estore_product_configuration_html( $product_config_html, $prod_id ) { 167 | global $wpdb; 168 | $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME; 169 | 170 | if ( empty( $prod_id ) ) { 171 | //New product add 172 | $slm_max_allowed_domains = ''; 173 | $slm_date_of_expiry = ''; 174 | } else { 175 | //Existing product edit 176 | 177 | //Retrieve the max domain value 178 | $product_meta = $wpdb->get_row( "SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_max_allowed_domains'", OBJECT ); 179 | if ( $product_meta ) { 180 | $slm_max_allowed_domains = $product_meta->meta_value; 181 | } else { 182 | $slm_max_allowed_domains = ''; 183 | } 184 | 185 | //Retrieve the expiry date value 186 | $product_meta = $wpdb->get_row( "SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_date_of_expiry'", OBJECT ); 187 | if ( $product_meta ) { 188 | $slm_date_of_expiry = $product_meta->meta_value; 189 | } else { 190 | $slm_date_of_expiry = ''; 191 | } 192 | } 193 | 194 | $product_config_html .= '
Software License Manager Plugin (Click to Expand)
'; 195 | 196 | $product_config_html .= ''; 200 | 201 | $product_config_html .= ''; 205 | 206 | $product_config_html .= '
Maximum Allowed Domains'; 197 | $product_config_html .= ''; 198 | $product_config_html .= '

Number of domains/installs in which this license can be used. Leave blank if you wish to use the default value set in the license manager plugin settings.

'; 199 | $product_config_html .= '
Number of Days before Expiry'; 202 | $product_config_html .= ' Days'; 203 | $product_config_html .= '

Number of days before expiry. The expiry date of the license will be set based on this value. For example, if you want the key to expire in 6 months then enter a value of 180.

'; 204 | $product_config_html .= '
'; 207 | 208 | return $product_config_html; 209 | } 210 | 211 | function slm_estore_new_product_added( $prod_dat_array, $prod_id ) { 212 | global $wpdb; 213 | $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME; 214 | 215 | //Save max domain value 216 | $fields = array(); 217 | $fields['prod_id'] = $prod_id; 218 | $fields['meta_key'] = 'slm_max_allowed_domains'; 219 | $fields['meta_value'] = $prod_dat_array['slm_max_allowed_domains']; 220 | $result = $wpdb->insert( $product_meta_table_name, $fields ); 221 | if ( ! $result ) { 222 | //insert query failed 223 | } 224 | 225 | //Save expiry date value 226 | $fields = array(); 227 | $fields['prod_id'] = $prod_id; 228 | $fields['meta_key'] = 'slm_date_of_expiry'; 229 | $fields['meta_value'] = $prod_dat_array['slm_date_of_expiry']; 230 | $result = $wpdb->insert( $product_meta_table_name, $fields ); 231 | if ( ! $result ) { 232 | //insert query failed 233 | } 234 | 235 | } 236 | 237 | function slm_estore_product_updated( $prod_dat_array, $prod_id ) { 238 | global $wpdb; 239 | $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME; 240 | 241 | //Find the existing value for the max domains field (for the given product) 242 | $product_meta = $wpdb->get_row( "SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_max_allowed_domains'", OBJECT ); 243 | if ( $product_meta ) { 244 | //Found existing value so lets update it 245 | //Better to do specific update (so the other meta values for example "download_limit_count" doesn't get set to empty). 246 | $meta_key_name = 'slm_max_allowed_domains'; 247 | $meta_value = $prod_dat_array['slm_max_allowed_domains']; 248 | $update_db_qry = "UPDATE $product_meta_table_name SET meta_value='$meta_value' WHERE prod_id='$prod_id' AND meta_key='$meta_key_name'"; 249 | $results = $wpdb->query( $update_db_qry ); 250 | 251 | } else { 252 | //No value for this field was there so lets insert one. 253 | $fields = array(); 254 | $fields['prod_id'] = $prod_id; 255 | $fields['meta_key'] = 'slm_max_allowed_domains'; 256 | $fields['meta_value'] = $prod_dat_array['slm_max_allowed_domains']; 257 | $result = $wpdb->insert( $product_meta_table_name, $fields ); 258 | } 259 | 260 | //Find the existing value for the expiry date field (for the given product) 261 | $product_meta = $wpdb->get_row( "SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_date_of_expiry'", OBJECT ); 262 | if ( $product_meta ) { 263 | //Found existing value so lets update it 264 | //Better to do specific update (so the other meta values for example "download_limit_count" doesn't get set to empty). 265 | $meta_key_name = 'slm_date_of_expiry'; 266 | $meta_value = $prod_dat_array['slm_date_of_expiry']; 267 | $update_db_qry = "UPDATE $product_meta_table_name SET meta_value='$meta_value' WHERE prod_id='$prod_id' AND meta_key='$meta_key_name'"; 268 | $results = $wpdb->query( $update_db_qry ); 269 | 270 | } else { 271 | //No value for this field was there so lets insert one. 272 | $fields = array(); 273 | $fields['prod_id'] = $prod_id; 274 | $fields['meta_key'] = 'slm_date_of_expiry'; 275 | $fields['meta_value'] = $prod_dat_array['slm_date_of_expiry']; 276 | $result = $wpdb->insert( $product_meta_table_name, $fields ); 277 | } 278 | 279 | } 280 | 281 | function slm_estore_product_deleted( $prod_id ) { 282 | global $wpdb; 283 | $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME; 284 | 285 | $result = $wpdb->delete( 286 | $product_meta_table_name, 287 | array( 288 | 'prod_id' => $prod_id, 289 | 'meta_key' => 'slm_max_allowed_domains', 290 | ) 291 | ); 292 | $result = $wpdb->delete( 293 | $product_meta_table_name, 294 | array( 295 | 'prod_id' => $prod_id, 296 | 'meta_key' => 'slm_date_of_expiry', 297 | ) 298 | ); 299 | } 300 | 301 | /************************************/ 302 | /*** End of WP eStore integration ***/ 303 | /************************************/ 304 | 305 | 306 | /*********************************************/ 307 | /*** WP eMember Plugin Integration Related ***/ 308 | /*********************************************/ 309 | 310 | add_shortcode( 'emember_show_slm_license_key', 'handle_emember_show_slm_license_key'); 311 | 312 | function handle_emember_show_slm_license_key( $args ){ 313 | if ( !class_exists('Emember_Auth')) { 314 | return "Error! WP eMember plugin is not active"; 315 | } 316 | 317 | $emember_auth = Emember_Auth::getInstance(); 318 | if ( !$emember_auth->isLoggedIn() ) { 319 | return "You are not logged into the site. Please log in."; 320 | } 321 | global $wpdb; 322 | $output = ""; 323 | 324 | //The member is logged-in. Find the WP eMember ID. 325 | $member_id = $emember_auth->getUserInfo('member_id'); 326 | $lk_table = SLM_TBL_LICENSE_KEYS; 327 | $sql_prep = $wpdb->prepare( "SELECT * FROM $lk_table WHERE user_ref = %s", $member_id ); 328 | $record = $wpdb->get_row( $sql_prep, OBJECT ); 329 | 330 | if ( $record ){ 331 | $license_key = $record->license_key; 332 | $output .= '
Your license key is: ' . $license_key . '
'; 333 | } else { 334 | //Could not find a record 335 | $output .= '
Could not find a key for your account.
'; 336 | } 337 | 338 | return $output; 339 | } -------------------------------------------------------------------------------- /software-license-manager/includes/slm-utility.php: -------------------------------------------------------------------------------- 1 | prepare( "SELECT * FROM $tbl_name WHERE lic_status !=%s", 'expired' );//Load the non-expired keys 14 | $licenses = $wpdb->get_results( $sql_prep, OBJECT ); 15 | if ( ! $licenses ) { 16 | SLM_Debug_Logger::log_debug_st( 'do_auto_key_expiry() - no license keys found.' ); 17 | return false; 18 | } 19 | 20 | foreach ( $licenses as $license ) { 21 | $key = $license->license_key; 22 | $expiry_date = $license->date_expiry; 23 | if ( $expiry_date == '0000-00-00' ) { 24 | SLM_Debug_Logger::log_debug_st( 'This key (' . $key . ") doesn't have a valid expiry date set. The expiry of this key will not be checked." ); 25 | continue; 26 | } 27 | 28 | $today_dt = new DateTime( $current_date ); 29 | $expire_dt = new DateTime( $expiry_date ); 30 | if ( $today_dt > $expire_dt ) { 31 | //This key has reached the expiry. So expire this key. 32 | SLM_Debug_Logger::log_debug_st( 'This key (' . $key . ') has expired. Expiry date: ' . $expiry_date . '. Setting license key status to expired.' ); 33 | $data = array( 'lic_status' => 'expired' ); 34 | $where = array( 'id' => $license->id ); 35 | $updated = $wpdb->update( $tbl_name, $data, $where ); 36 | do_action( 'slm_license_key_expired', $license->id );//Trigger the license expired action hook. 37 | } 38 | } 39 | } 40 | 41 | /* 42 | * Deletes a license key from the licenses table 43 | */ 44 | static function delete_license_key_by_row_id( $key_row_id ) { 45 | global $wpdb; 46 | $license_table = SLM_TBL_LICENSE_KEYS; 47 | 48 | //First delete the registered domains entry of this key (if any). 49 | SLM_Utility::delete_registered_domains_of_key( $key_row_id ); 50 | 51 | //Now, delete the key from the licenses table. 52 | $wpdb->delete( $license_table, array( 'id' => $key_row_id ) ); 53 | 54 | } 55 | 56 | /* 57 | * Deletes any registered domains info from the domain table for the given key's row id. 58 | */ 59 | static function delete_registered_domains_of_key( $key_row_id ) { 60 | global $slm_debug_logger; 61 | global $wpdb; 62 | $reg_table = SLM_TBL_LIC_DOMAIN; 63 | $sql_prep = $wpdb->prepare( "SELECT * FROM $reg_table WHERE lic_key_id = %s", $key_row_id ); 64 | $reg_domains = $wpdb->get_results( $sql_prep, OBJECT ); 65 | foreach ( $reg_domains as $domain ) { 66 | $row_to_delete = $domain->id; 67 | $wpdb->delete( $reg_table, array( 'id' => $row_to_delete ) ); 68 | //$slm_debug_logger->log_debug("Registered domain with row id (".$row_to_delete.") deleted."); 69 | } 70 | } 71 | 72 | 73 | /** 74 | * Get remote IP address. 75 | * @link http://stackoverflow.com/questions/1634782/what-is-the-most-accurate-way-to-retrieve-a-users-correct-ip-address-in-php 76 | * 77 | * @param bool $ignore_private_and_reserved Ignore IPs that fall into private or reserved IP ranges. 78 | * @return mixed IP address as a string or null, if remote IP address cannot be determined (or is ignored). 79 | */ 80 | static function get_ip_address( $ignore_private_and_reserved = false ) { 81 | $flags = $ignore_private_and_reserved ? ( FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) : 0; 82 | foreach ( array( 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR' ) as $key ) { 83 | if ( array_key_exists( $key, $_SERVER ) === true ) { 84 | foreach ( explode( ',', $_SERVER[ $key ] ) as $ip ) { 85 | $ip = trim( $ip ); // just to be safe 86 | 87 | if ( filter_var( $ip, FILTER_VALIDATE_IP, $flags ) !== false ) { 88 | return $ip; 89 | } 90 | } 91 | } 92 | } 93 | return ''; 94 | } 95 | 96 | static function sanitize_strip_trim_slm_text( $text ) { 97 | $text = strip_tags( $text ); 98 | $text = htmlspecialchars( $text ); 99 | $text = sanitize_text_field( $text ); 100 | $text = trim( $text ); 101 | return $text; 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /software-license-manager/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arsenal21/software-license-manager/b94b26017c7fa4a55732a06f811407abcf6c1b69/software-license-manager/index.html -------------------------------------------------------------------------------- /software-license-manager/js/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arsenal21/software-license-manager/b94b26017c7fa4a55732a06f811407abcf6c1b69/software-license-manager/js/index.html -------------------------------------------------------------------------------- /software-license-manager/js/wplm-custom-admin.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function ($) { 2 | //Add date picker listener on date fields 3 | if ($.fn.datepicker) { 4 | $('.wplm_pick_date').datepicker({ 5 | dateFormat: 'yy-mm-dd' 6 | }); 7 | } 8 | 9 | //Add other admin side only jquery code below 10 | 11 | }); -------------------------------------------------------------------------------- /software-license-manager/menu/includes/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arsenal21/software-license-manager/b94b26017c7fa4a55732a06f811407abcf6c1b69/software-license-manager/menu/includes/index.html -------------------------------------------------------------------------------- /software-license-manager/menu/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arsenal21/software-license-manager/b94b26017c7fa4a55732a06f811407abcf6c1b69/software-license-manager/menu/index.html -------------------------------------------------------------------------------- /software-license-manager/menu/slm-add-licenses.php: -------------------------------------------------------------------------------- 1 | '; 28 | echo '

Add/Edit Licenses

'; 29 | echo '
'; 30 | 31 | // If product is being edited, grab current product info. 32 | if ( isset( $_GET['edit_record'] ) ) { 33 | $errors = ''; 34 | $id = intval( $_GET['edit_record'] ); 35 | $lk_table = SLM_TBL_LICENSE_KEYS; 36 | $sql_prep = $wpdb->prepare( "SELECT * FROM $lk_table WHERE id = %s", $id ); 37 | $record = $wpdb->get_row( $sql_prep, OBJECT ); 38 | $license_key = $record->license_key; 39 | $max_domains = $record->max_allowed_domains; 40 | $license_status = $record->lic_status; 41 | $first_name = $record->first_name; 42 | $last_name = $record->last_name; 43 | $email = $record->email; 44 | $company_name = $record->company_name; 45 | $txn_id = $record->txn_id; 46 | $reset_count = $record->manual_reset_count; 47 | $created_date = $record->date_created; 48 | $renewed_date = $record->date_renewed; 49 | $expiry_date = $record->date_expiry; 50 | $product_ref = $record->product_ref; 51 | $subscr_id = $record->subscr_id; 52 | $user_ref = $record->user_ref; 53 | } 54 | 55 | if ( isset( $_POST['save_record'] ) ) { 56 | 57 | // Check nonce. 58 | check_admin_referer( 'slm_add_edit_nonce_action', 'slm_add_edit_nonce_val' ); 59 | 60 | do_action( 'slm_add_edit_interface_save_submission' ); 61 | 62 | // TODO - do some validation. 63 | $license_key = sanitize_text_field( $_POST['license_key'] ); 64 | $max_domains = intval( $_POST['max_allowed_domains'] ); 65 | $license_status = sanitize_text_field( $_POST['lic_status'] ); 66 | $first_name = sanitize_text_field( $_POST['first_name'] ); 67 | $last_name = sanitize_text_field( $_POST['last_name'] ); 68 | $email = sanitize_email( $_POST['email'] ); 69 | $company_name = sanitize_text_field( $_POST['company_name'] ); 70 | $txn_id = sanitize_text_field( $_POST['txn_id'] ); 71 | $reset_count = sanitize_text_field( $_POST['manual_reset_count'] ); 72 | $created_date = sanitize_text_field( $_POST['date_created'] ); 73 | $renewed_date = sanitize_text_field( $_POST['date_renewed'] ); 74 | $expiry_date = sanitize_text_field( $_POST['date_expiry'] ); 75 | $product_ref = sanitize_text_field( $_POST['product_ref'] ); 76 | $subscr_id = sanitize_text_field( $_POST['subscr_id'] ); 77 | $user_ref = sanitize_text_field( $_POST['user_ref'] ); 78 | 79 | if ( empty( $created_date ) ) { 80 | $created_date = $current_date; 81 | } 82 | if ( empty( $renewed_date ) ) { 83 | $renewed_date = $current_date; 84 | } 85 | if ( empty( $expiry_date ) ) { 86 | $expiry_date = $current_date_plus_1year; 87 | } 88 | 89 | // Save the entry to the database. 90 | $fields = array(); 91 | $fields['license_key'] = $license_key; 92 | $fields['max_allowed_domains'] = $max_domains; 93 | $fields['lic_status'] = $license_status; 94 | $fields['first_name'] = $first_name; 95 | $fields['last_name'] = $last_name; 96 | $fields['email'] = $email; 97 | $fields['company_name'] = $company_name; 98 | $fields['txn_id'] = $txn_id; 99 | $fields['manual_reset_count'] = $reset_count; 100 | $fields['date_created'] = $created_date; 101 | $fields['date_renewed'] = $renewed_date; 102 | $fields['date_expiry'] = $expiry_date; 103 | $fields['product_ref'] = $product_ref; 104 | $fields['subscr_id'] = $subscr_id; 105 | $fields['user_ref'] = $user_ref; 106 | 107 | $id = isset( $_POST['edit_record'] ) ? intval( $_POST['edit_record'] ) : ''; 108 | $lk_table = SLM_TBL_LICENSE_KEYS; 109 | if ( empty( $id ) ) {// Insert into database. 110 | $result = $wpdb->insert( $lk_table, $fields ); 111 | $id = $wpdb->insert_id; 112 | if ( false === $result ) { 113 | $errors .= __( 'Record could not be inserted into the database!', 'slm' ); 114 | } 115 | } else { // Update record. 116 | $where = array( 'id' => $id ); 117 | $updated = $wpdb->update( $lk_table, $fields, $where ); 118 | if ( false === $updated ) { 119 | // TODO - log error. 120 | $errors .= __( 'Update of the license key table failed!', 'slm' ); 121 | } 122 | } 123 | 124 | if ( empty( $errors ) ) { 125 | $message = 'Record successfully saved!'; 126 | echo '

'; 127 | echo esc_html( $message ); 128 | echo '

'; 129 | } else { 130 | echo '
' . esc_html( $errors ) . '
'; 131 | } 132 | 133 | $data = array( 134 | 'row_id' => $id, 135 | 'key' => $license_key, 136 | ); 137 | do_action( 'slm_add_edit_interface_save_record_processed', $data ); 138 | 139 | } 140 | 141 | ?> 142 | 190 | You can add a new license or edit an existing one from this interface. 191 |

192 | 193 |
194 |

195 |
196 | 197 |
198 | 199 | 200 | 201 | '; 204 | } else { 205 | if ( ! isset( $editing_record ) ) {// Create an empty object. 206 | $editing_record = new stdClass(); 207 | } 208 | // Auto generate unique key. 209 | $lic_key_prefix = isset($slm_options['lic_prefix']) && ! empty( $slm_options['lic_prefix'] ) ? $slm_options['lic_prefix'] : ''; 210 | if ( !empty($lic_key_prefix) ) { 211 | $license_key = uniqid( $lic_key_prefix ); 212 | } else { 213 | $license_key = uniqid(); 214 | } 215 | $license_key = apply_filters( 'slm_generate_license_key', $license_key ); 216 | } 217 | ?> 218 | 219 | 220 | 221 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 240 | 241 | prepare( "SELECT * FROM `$reg_table` WHERE `lic_key_id` = %s", $id ); 246 | $reg_domains = $wpdb->get_results( $sql_prep, OBJECT ); 247 | ?> 248 | 249 | 250 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 328 | 329 | 330 | 331 | 332 | 334 | 335 | 336 | 337 | 338 | 340 | 341 | 342 | 343 | 344 | 346 | 347 | 348 | 349 | 350 | 352 | 353 | 354 | 355 | 356 | 358 | 359 | 360 | 361 | 362 | 364 | 365 | 366 |
License Key 222 |
The unique license key. When adding a new record it automatically generates a unique key in this field for you. You can change this value to customize the key if you like.
Maximum Allowed Domains
Number of domains/installs in which this license can be used.
License Status 233 | 239 |
Registered Domains 251 | 0 ) { ?> 252 | 253 |
254 | 255 | ×'; 258 | foreach ( $reg_domains as $reg_domain ) : 259 | ?> 260 | > 261 | 282 | 283 | 284 | 288 |
262 | id ), 267 | esc_attr( wp_create_nonce( sprintf( 'slm_delete_domain_lic_%s_id_%s', $id, $reg_domain->id ) ) ) 268 | ), 269 | array( 270 | 'a' => array( 271 | 'class' => array(), 272 | 'href' => array(), 273 | 'title' => array(), 274 | 'data-domain-id' => array(), 275 | 'data-lic-id' => array(), 276 | 'data-nonce' => array(), 277 | ), 278 | ) 279 | ); 280 | ?> 281 | registered_domain ); ?>
289 |
290 | 295 |
First Name
License user's first name
Last Name
License user's last name
Email Address
License user's email address
Company Name
License user's company name
Unique Transaction ID
The unique transaction ID associated with this license key
Manual Reset Count 327 |
The number of times this license has been manually reset by the admin (use it if you want to keep track of it). It can be helpful for the admin to keep track of manual reset counts.
Date Created 333 |
Creation date of license.
Date Renewed 339 |
Renewal date of license.
Date of Expiry 345 |
Expiry date of license.
Product Reference 351 |
The product that this license applies to (if any).
Subscriber ID 357 |
The Subscriber ID (if any). Can be useful if you are using the license key with a recurring payment plan.
User Reference 363 |
The User ID of the user that this license applies to (if any). Can be useful if you want to connect your licenses to some kind of member/user management system.
367 | 368 | $id, 371 | 'key' => $license_key, 372 | ); 373 | do_action( 'slm_add_edit_interface_above_submit', $data ); 374 | ?> 375 | 376 |
377 | 378 |
379 |
380 |
381 | Manage Licenses

382 |
383 | 384 | 385 | 450 | '; 6 | echo '

License Manager Admin Functions

'; 7 | echo '
'; 8 | 9 | $slm_options = get_option( 'slm_plugin_options' ); 10 | 11 | $post_url = ''; 12 | 13 | if ( isset( $_POST['send_deactivation_request'] ) ) { 14 | check_admin_referer( 'slm_send_deact_req' ); 15 | $post_url = filter_input( INPUT_POST, 'lic_mgr_deactivation_req_url', FILTER_SANITIZE_URL ); 16 | $secretKeyForVerification = $slm_options['lic_verification_secret']; 17 | $data = array(); 18 | $data['secret_key'] = $secretKeyForVerification; 19 | 20 | if (empty($post_url)){ 21 | wp_die('The URL value is empty. Go back and enter a valid URL value.'); 22 | } 23 | 24 | // Send query to the license manager server 25 | $response = wp_remote_get(add_query_arg($data, $post_url), array('timeout' => 20, 'sslverify' => false)); 26 | 27 | // Check for error in the response 28 | if (is_wp_error($response)){ 29 | echo "Unexpected Error! The query returned with an error."; 30 | } 31 | 32 | // License data. 33 | $license_data = json_decode(wp_remote_retrieve_body($response)); 34 | 35 | echo '

'; 36 | echo 'Request sent to the specified URL!'; 37 | echo '

'; 38 | echo '

Variable dump of the response below:

'; 39 | var_dump($license_data); 40 | } 41 | ?> 42 |
43 |
44 |

45 |
46 |
Enter the URL where the license deactivation message will be sent to 47 |

48 |
49 | 50 | 51 |
52 | 53 |
54 |
55 |
56 |
'; 58 | echo '
'; 59 | } 60 | -------------------------------------------------------------------------------- /software-license-manager/menu/slm-admin-init.php: -------------------------------------------------------------------------------- 1 | 5 | 9 | '; 16 | echo '

License Manager Integration Help

'; 17 | echo '
'; 18 | 19 | echo '
'; 20 | echo '

For information, updates and documentation, please visit the License Manager Documentation page.

'; 21 | echo '
'; 22 | 23 | echo '

Some Key Variable Info for Your Install

'; 24 | 25 | $api_query_post_url = SLM_SITE_HOME_URL; 26 | echo 'The License API Query POST URL For Your Installation'; 27 | echo '
' . esc_url( $api_query_post_url ) . '
'; 28 | 29 | echo 'The License Activation or Deactivation API secret key'; 30 | echo '
' . esc_html( $secret_verification_key ) . '
'; 31 | 32 | echo 'The License Creation API secret key'; 33 | echo '
' . esc_html( $creation_secret_key ) . '
'; 34 | 35 | echo '

3rd Party Integration Documentation

'; 36 | 37 | echo '
'; 38 | echo '

Integration documentation is available on the License Manager Documentation page. You can also download a sample plugin code from that page.

'; 39 | echo '
'; 40 | 41 | echo '
'; 42 | echo ''; 43 | } 44 | -------------------------------------------------------------------------------- /software-license-manager/menu/slm-lic-settings.php: -------------------------------------------------------------------------------- 1 | '; 6 | echo '

WP License Manager Settings v' . esc_html( WP_LICENSE_MANAGER_VERSION ) . '

'; 7 | echo '
'; 8 | 9 | wp_lic_mgr_general_settings(); 10 | 11 | echo '
'; 12 | echo ''; 13 | } 14 | 15 | function wp_lic_mgr_general_settings() { 16 | 17 | if ( isset( $_REQUEST['slm_reset_log'] ) ) { 18 | check_admin_referer( 'slm_reset_debug_log', 'slm_reset_debug_log_nonce' ); 19 | //$slm_logger = new SLM_Debug_Logger(); 20 | global $slm_debug_logger; 21 | $slm_debug_logger->reset_log_file(); 22 | $slm_debug_logger->reset_log_file( 'log-cron-job.txt' ); 23 | echo '

Debug log files have been reset!

'; 24 | } 25 | 26 | if ( isset( $_POST['slm_save_settings'] ) ) { 27 | 28 | //Check nonce 29 | check_admin_referer( 'slm_settings_nonce_action', 'slm_settings_nonce_val' ); 30 | 31 | $default_max_domains = filter_input( INPUT_POST, 'default_max_domains', FILTER_SANITIZE_NUMBER_INT ); 32 | $default_max_domains = empty( $default_max_domains ) ? 1 : $default_max_domains; 33 | 34 | $lic_creation_secret = isset( $_POST['lic_creation_secret'] ) ? sanitize_text_field( stripslashes ( $_POST['lic_creation_secret'] ) ) : ''; 35 | 36 | $lic_prefix = isset( $_POST['lic_prefix'] ) ? sanitize_text_field( stripslashes ( $_POST['lic_prefix'] ) ) : ''; 37 | $lic_prefix = empty( $lic_prefix ) ? '' : SLM_Utility::sanitize_strip_trim_slm_text( $lic_prefix ); 38 | 39 | $lic_verification_secret = isset( $_POST['lic_verification_secret'] ) ? sanitize_text_field( stripslashes ( $_POST['lic_verification_secret'] ) ) : ''; 40 | 41 | $curr_opts = get_option( 'slm_plugin_options' ); 42 | 43 | $options = array( 44 | 'lic_creation_secret' => $lic_creation_secret, 45 | 'lic_prefix' => $lic_prefix, 46 | 'default_max_domains' => $default_max_domains, 47 | 'lic_verification_secret' => $lic_verification_secret, 48 | 'enable_auto_key_expiry' => isset( $_POST['enable_auto_key_expiry'] ) ? '1' : '', 49 | 'enable_debug' => isset( $_POST['enable_debug'] ) ? '1' : '', 50 | ); 51 | 52 | $options = array_merge( $curr_opts, $options ); 53 | 54 | update_option( 'slm_plugin_options', $options ); 55 | 56 | echo '

'; 57 | echo 'Options Updated!'; 58 | echo '

'; 59 | } 60 | 61 | $options = get_option( 'slm_plugin_options' ); 62 | 63 | $secret_key = isset($options['lic_creation_secret']) && !empty($options['lic_creation_secret']) ? $options['lic_creation_secret'] : ''; 64 | if ( empty( $secret_key ) ) { 65 | $secret_key = uniqid( '', true ); 66 | } 67 | $secret_verification_key = isset($options['lic_verification_secret']) && !empty($options['lic_verification_secret']) ? $options['lic_verification_secret'] : ''; 68 | if ( empty( $secret_verification_key ) ) { 69 | $secret_verification_key = uniqid( '', true ); 70 | } 71 | 72 | $lic_prefix = isset($options['lic_prefix']) && !empty($options['lic_prefix']) ? $options['lic_prefix'] : ''; 73 | $default_max_domains = isset($options['default_max_domains']) && !empty($options['default_max_domains']) ? $options['default_max_domains'] : ''; 74 | $enable_auto_key_expiry = isset($options['enable_auto_key_expiry']) && !empty($options['enable_auto_key_expiry']) ? 'checked="checked"' : ''; 75 | $enable_debug_checked = isset($options['enable_debug']) && !empty($options['enable_debug']) ? 'checked="checked"' : ''; 76 | ?> 77 |

For information, updates and documentation, please visit the License Manager Documentation page.

78 | 79 |
80 |

81 |
82 | 83 |

1. First register a key at purchase time.

84 |

2. Add the code so at activation time it asks for the key.

85 |

3. Integrate the real time online key verification part.

86 |
87 | 88 |
89 | 90 | 91 |
92 |

93 |
94 | 95 | 96 | 97 | 98 | 100 | 101 | 102 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 112 | 113 | 114 | 115 | 116 | 118 | 119 | 120 | 121 | 122 | 126 | 127 |
Secret Key for License Creation 99 |
This secret key will be used to authenticate any license creation request. You can change it with something random.
Secret Key for License Verification Requests 105 |
This secret key will be used to authenticate any license verification request from customer's site. Important! Do not change this value once your customers start to use your product(s)!
License Key Prefix 111 |
You can optionally specify a prefix for the license keys. This prefix will be added to the uniquely generated license keys.
Maximum Allowed Domains 117 |
Maximum number of domains/installs which each license is valid for (default value).
Auto Expire License Keys value="1"/> 123 |

When enabled, it will automatically set the status of a license key to "Expired" when the expiry date value of the key is reached. 124 | It doesn't remotely deactivate a key. It simply changes the status of the key in your database to expired.

125 |
128 |
129 | 130 |
131 |

132 |
133 | 134 | 135 | 136 | 137 | 142 | 143 | 144 |
Enable Debug Logging value="1"/> 138 |

If checked, debug output will be written to log files (keep it disabled unless you are troubleshooting).

139 |
- View debug log file by clicking here. 140 |
- Reset debug log file by clicking here. 141 |
145 |
146 | 147 |
148 | 149 |
150 |
151 | 'item', //singular name of the listed records 16 | 'plural' => 'items', //plural name of the listed records 17 | 'ajax' => false, //does this table support ajax? 18 | ) 19 | ); 20 | 21 | } 22 | 23 | function column_default( $item, $column_name ) { 24 | return $item[ $column_name ]; 25 | } 26 | 27 | function column_id( $item ) { 28 | $row_id = $item['id']; 29 | $actions = array( 30 | 'edit' => sprintf( 'Edit', $row_id ), 31 | 'delete' => sprintf( 32 | 'Delete', 33 | $row_id, 34 | wp_create_nonce( 'slm-delete-license-' . $row_id ) 35 | ), 36 | ); 37 | return sprintf( 38 | '%1$s %2$s', 39 | /*$1%s*/ $item['id'], 40 | /*$2%s*/ $this->row_actions( $actions ) 41 | ); 42 | } 43 | 44 | 45 | function column_cb( $item ) { 46 | return sprintf( 47 | '', 48 | /*$1%s*/ $this->_args['singular'], //Let's simply repurpose the table's singular label 49 | /*$2%s*/ $item['id'] //The value of the checkbox should be the record's id 50 | ); 51 | } 52 | 53 | function column_active( $item ) { 54 | if ( $item['active'] == 1 ) { 55 | return 'active'; 56 | } else { 57 | return 'inactive'; 58 | } 59 | } 60 | 61 | function get_columns() { 62 | $columns = array( 63 | 'cb' => '', // Render a checkbox. 64 | 'id' => 'ID', 65 | 'license_key' => 'License Key', 66 | 'lic_status' => 'Status', 67 | 'max_allowed_domains' => 'Domains', 68 | 'email' => 'Registered Email', 69 | 'date_created' => 'Date Created', 70 | 'date_renewed' => 'Date Renewed', 71 | 'date_expiry' => 'Expiry', 72 | 'product_ref' => 'Product Reference', 73 | ); 74 | return $columns; 75 | } 76 | 77 | function get_sortable_columns() { 78 | $sortable_columns = array( 79 | 'id' => array( 'id', false ), 80 | 'license_key' => array( 'license_key', false ), 81 | 'lic_status' => array( 'lic_status', false ), 82 | 'date_created' => array( 'date_created', false ), 83 | 'date_renewed' => array( 'date_renewed', false ), 84 | 'date_expiry' => array( 'date_expiry', false ), 85 | ); 86 | return $sortable_columns; 87 | } 88 | 89 | function get_bulk_actions() { 90 | $actions = array( 91 | 'delete' => 'Delete', 92 | ); 93 | return $actions; 94 | } 95 | 96 | function process_bulk_action() { 97 | if ( 'delete' === $this->current_action() ) { 98 | check_admin_referer( 'bulk-' . $this->_args['plural'] ); 99 | //Process delete bulk actions 100 | if ( ! isset( $_REQUEST['item'] ) ) { 101 | $error_msg = __( 'Error - Please select some records using the checkboxes', 'slm' ); 102 | echo '

' . esc_html( $error_msg ) . '

'; 103 | return; 104 | } else { 105 | $nvp_key = $this->_args['singular']; 106 | $records_to_delete = filter_input( INPUT_GET, $nvp_key, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ); 107 | foreach ( $records_to_delete as $row ) { 108 | SLM_Utility::delete_license_key_by_row_id( $row ); 109 | } 110 | echo '

Selected records deleted successfully!

'; 111 | } 112 | } 113 | } 114 | 115 | 116 | /* 117 | * This function will delete the selected license key entries from the DB. 118 | */ 119 | function delete_license_key( $key_row_id ) { 120 | SLM_Utility::delete_license_key_by_row_id( $key_row_id ); 121 | echo '

'; 122 | echo 'The selected entry was deleted successfully!'; 123 | echo '

'; 124 | } 125 | 126 | function search_box( $text, $input_id ) { 127 | if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) { 128 | return; 129 | } 130 | 131 | $input_id = $input_id . '-search-input'; 132 | 133 | if ( ! empty( $_REQUEST['orderby'] ) ) { 134 | echo ''; 135 | } 136 | if ( ! empty( $_REQUEST['order'] ) ) { 137 | echo ''; 138 | } 139 | if ( ! empty( $_REQUEST['post_mime_type'] ) ) { 140 | echo ''; 141 | } 142 | if ( ! empty( $_REQUEST['detached'] ) ) { 143 | echo ''; 144 | } 145 | ?> 146 | 147 |
148 |

149 |
150 |

Search for a license by using email, name, key, domain or transaction ID

151 | 152 | 153 | 'search-submit' ) ); ?> 154 |
155 |
156 | 157 | 158 | get_pagenum(); 167 | $columns = $this->get_columns(); 168 | $hidden = array(); 169 | $sortable = $this->get_sortable_columns(); 170 | 171 | $this->_column_headers = array( $columns, $hidden, $sortable ); 172 | 173 | $this->process_bulk_action(); 174 | 175 | global $wpdb; 176 | $license_table = SLM_TBL_LICENSE_KEYS; 177 | $domain_table = SLM_TBL_LIC_DOMAIN; 178 | 179 | /** 180 | * Ordering parameters: 181 | * Parameters that are going to be used to order the result. 182 | */ 183 | $orderby = ! empty( $_GET['orderby'] ) ? wp_strip_all_tags( $_GET['orderby'] ) : 'id'; 184 | $order = ! empty( $_GET['order'] ) ? wp_strip_all_tags( $_GET['order'] ) : 'DESC'; 185 | 186 | $order_str = sanitize_sql_orderby( $orderby . ' ' . $order ); 187 | 188 | $limit_from = ( $current_page - 1 ) * $per_page; 189 | 190 | if ( ! empty( $_REQUEST['s'] ) ) { 191 | $search_term = trim( sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) ); 192 | $placeholder = '%' . $wpdb->esc_like( $search_term ) . '%'; 193 | 194 | $select = "SELECT `lk` . * , CONCAT( COUNT( `rd` . `lic_key_id` ), '/', `lk` . `max_allowed_domains` ) AS `max_allowed_domains`"; 195 | 196 | $after_select = "FROM `$license_table` `lk` 197 | LEFT JOIN `$domain_table` `rd` ON `lk`.`id` = `rd`.`lic_key_id` 198 | WHERE `lk`.`license_key` LIKE %s 199 | OR `lk`.`email` LIKE %s 200 | OR `lk`.`txn_id` LIKE %s 201 | OR `lk`.`first_name` LIKE %s 202 | OR `lk`.`last_name` LIKE %s 203 | OR `rd`.`registered_domain` LIKE %s"; 204 | 205 | $after_query = "GROUP BY `lk` . `id` ORDER BY $order_str 206 | LIMIT $limit_from, $per_page"; 207 | 208 | $q = "$select $after_select $after_query"; 209 | 210 | $data = $wpdb->get_results( 211 | $wpdb->prepare( 212 | $q, 213 | $placeholder, 214 | $placeholder, 215 | $placeholder, 216 | $placeholder, 217 | $placeholder, 218 | $placeholder 219 | ), 220 | ARRAY_A 221 | ); 222 | 223 | // SQL query for counting the total number of distinct license keys. 224 | // Use COUNT(DISTINCT lk.id): This ensures that you're counting the number of distinct license keys (not the number of domains) 225 | $found_rows_q = $wpdb->prepare( 226 | "SELECT COUNT(DISTINCT `lk`.`id`) 227 | $after_select", 228 | $placeholder, 229 | $placeholder, 230 | $placeholder, 231 | $placeholder, 232 | $placeholder, 233 | $placeholder 234 | ); 235 | 236 | // Get the total number of items. 237 | $total_items = intval( $wpdb->get_var( $found_rows_q ) ); 238 | } else { 239 | $after_select = "FROM `$license_table` `lk` 240 | LEFT JOIN `$domain_table` `rd` 241 | ON `lk` . `id` = `rd` . `lic_key_id`"; 242 | 243 | $after_query = "GROUP BY `lk` . `id` 244 | ORDER BY $order_str 245 | LIMIT $limit_from, $per_page"; 246 | 247 | $q = "SELECT `lk` . * , 248 | CONCAT( COUNT( `rd` . `lic_key_id` ), '/', `lk` . `max_allowed_domains` ) as `max_allowed_domains` 249 | $after_select$after_query"; 250 | 251 | $data = $wpdb->get_results( $q, ARRAY_A ); 252 | 253 | // SQL query for counting the total number of distinct license keys. 254 | //$found_rows_q = "SELECT COUNT( * ) $after_select";//Old query. 255 | //Use COUNT(DISTINCT lk.id): This ensures that you're counting the number of distinct license keys (not the number of domains) 256 | $found_rows_q = "SELECT COUNT(DISTINCT `lk`.`id`) $after_select"; 257 | 258 | // Get the total number of items. 259 | $total_items = intval( $wpdb->get_var( $found_rows_q ) ); 260 | } 261 | 262 | $this->items = $data; 263 | $this->set_pagination_args( 264 | array( 265 | 'total_items' => $total_items, // WE have to calculate the total number of items. 266 | 'per_page' => $per_page, // WE have to determine how many items to show on a page. 267 | 'total_pages' => ceil( $total_items / $per_page ), // WE have to calculate the total number of pages. 268 | ) 269 | ); 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /software-license-manager/menu/slm-manage-licenses.php: -------------------------------------------------------------------------------- 1 | delete_license_key( intval( $id ) ); 24 | } 25 | break; 26 | default: 27 | break; 28 | } 29 | 30 | $page = isset( $_GET['page'] ) ? sanitize_text_field( stripslashes ( $_GET['page'] ) ) : ''; 31 | 32 | // Fetch, prepare, sort, and filter our data... 33 | $license_list->prepare_items(); 34 | 35 | ?> 36 | 65 |
66 |

Manage Licenses 67 | Add New License 68 |

69 |
70 |
71 |
72 | 73 | 74 | search_box( 'Search', 'slm_search' ); ?> 75 | 76 |
77 |

78 |
79 | 80 | 81 | 82 | display(); ?> 83 |
84 |
85 |
86 |
87 |
88 |
89 | 94 | ' . (__( "Settings", "slm" )) . ''; 58 | array_unshift( $links, $settings_link ); 59 | } 60 | return $links; 61 | } 62 | add_filter( 'plugin_action_links', 'slm_add_settings_link', 10, 2 ); -------------------------------------------------------------------------------- /software-license-manager/slm_installer.php: -------------------------------------------------------------------------------- 1 | charset ) ) { 12 | $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset"; 13 | } else { 14 | $charset_collate = 'DEFAULT CHARSET=utf8'; 15 | } 16 | if ( ! empty( $wpdb->collate ) ) { 17 | $charset_collate .= " COLLATE $wpdb->collate"; 18 | } 19 | 20 | $lk_tbl_sql = 'CREATE TABLE ' . $lic_key_table . " ( 21 | id int(12) NOT NULL auto_increment, 22 | license_key varchar(255) NOT NULL, 23 | max_allowed_domains int(12) NOT NULL, 24 | lic_status ENUM('pending', 'active', 'blocked', 'expired') NOT NULL DEFAULT 'pending', 25 | first_name varchar(32) NOT NULL default '', 26 | last_name varchar(32) NOT NULL default '', 27 | email varchar(64) NOT NULL, 28 | company_name varchar(100) NOT NULL default '', 29 | txn_id varchar(64) NOT NULL default '', 30 | manual_reset_count varchar(128) NOT NULL default '', 31 | date_created date NOT NULL DEFAULT '0000-00-00', 32 | date_renewed date NOT NULL DEFAULT '0000-00-00', 33 | date_expiry date NOT NULL DEFAULT '0000-00-00', 34 | product_ref varchar(255) NOT NULL default '', 35 | subscr_id varchar(128) NOT NULL default '', 36 | user_ref varchar(255) NOT NULL default '', 37 | PRIMARY KEY (id), 38 | KEY `max_allowed_domains` (`max_allowed_domains`) 39 | )" . $charset_collate . ';'; 40 | dbDelta( $lk_tbl_sql ); 41 | 42 | $ld_tbl_sql = 'CREATE TABLE ' . $lic_domain_table . ' ( 43 | id INT NOT NULL AUTO_INCREMENT , 44 | lic_key_id INT NOT NULL , 45 | lic_key varchar(255) NOT NULL , 46 | registered_domain text NOT NULL , 47 | item_reference varchar(255) NOT NULL, 48 | PRIMARY KEY ( id ), 49 | KEY `lic_key_id` (`lic_key_id`) 50 | )' . $charset_collate . ';'; 51 | dbDelta( $ld_tbl_sql ); 52 | 53 | update_option( 'wp_lic_mgr_db_version', WP_LICENSE_MANAGER_DB_VERSION ); 54 | 55 | // Add default options 56 | $options = array( 57 | 'lic_creation_secret' => uniqid( '', true ), 58 | 'lic_prefix' => '', 59 | 'default_max_domains' => '1', 60 | 'lic_verification_secret' => uniqid( '', true ), 61 | 'enable_debug' => '', 62 | ); 63 | add_option( 'slm_plugin_options', $options ); 64 | -------------------------------------------------------------------------------- /software-license-manager/slm_plugin_core.php: -------------------------------------------------------------------------------- 1 | prefix . 'lic_key_tbl' ); 6 | define( 'SLM_TBL_LIC_DOMAIN', $wpdb->prefix . 'lic_reg_domain_tbl' ); 7 | define( 'SLM_MANAGEMENT_PERMISSION', apply_filters( 'slm_management_permission_role', 'manage_options' ) ); 8 | define( 'SLM_MAIN_MENU_SLUG', 'slm-main' ); 9 | define( 'SLM_MENU_ICON', 'dashicons-lock' ); 10 | 11 | //Includes 12 | require_once 'includes/slm-debug-logger.php'; 13 | require_once 'includes/slm-error-codes.php'; 14 | require_once 'includes/slm-utility.php'; 15 | require_once 'includes/slm-init-time-tasks.php'; 16 | require_once 'includes/slm-api-utility.php'; 17 | require_once 'includes/slm-api-listener.php'; 18 | require_once 'includes/slm-third-party-integration.php'; 19 | //Include admin side only files 20 | if ( is_admin() ) { 21 | include_once 'menu/slm-admin-init.php'; 22 | } 23 | 24 | //Action hooks 25 | add_action( 'init', 'slm_init_handler' ); 26 | add_action( 'plugins_loaded', 'slm_plugins_loaded_handler' ); 27 | 28 | //Initialize debug logger 29 | global $slm_debug_logger; 30 | $slm_debug_logger = new SLM_Debug_Logger(); 31 | 32 | //Do init time tasks 33 | function slm_init_handler() { 34 | $init_task = new SLM_Init_Time_Tasks(); 35 | $api_listener = new SLM_API_Listener(); 36 | } 37 | 38 | //Do plugins loaded time tasks 39 | function slm_plugins_loaded_handler() { 40 | //Runs when plugins_loaded action gets fired 41 | if ( is_admin() ) { 42 | //Check if db update needed 43 | if ( get_option( 'wp_lic_mgr_db_version' ) != WP_LICENSE_MANAGER_DB_VERSION ) { 44 | require_once dirname( __FILE__ ) . '/slm_installer.php'; 45 | } 46 | } 47 | 48 | } 49 | 50 | //TODO - need to move this to an ajax handler file 51 | add_action( 'wp_ajax_slm_delete_domain', 'slm_del_reg_dom' ); 52 | function slm_del_reg_dom() { 53 | $out = array( 'status' => 'fail' ); 54 | 55 | if ( ! current_user_can( 'administrator' ) ) { 56 | wp_send_json( $out ); 57 | } 58 | 59 | global $wpdb; 60 | 61 | $lic_id = filter_input( INPUT_POST, 'lic_id', FILTER_SANITIZE_NUMBER_INT, FILTER_VALIDATE_INT ); 62 | $domain_id = filter_input( INPUT_POST, 'domain_id', FILTER_SANITIZE_NUMBER_INT, FILTER_VALIDATE_INT ); 63 | 64 | if ( empty( $lic_id ) || empty( $domain_id ) ) { 65 | wp_send_json( $out ); 66 | } 67 | 68 | $reg_table = SLM_TBL_LIC_DOMAIN; 69 | 70 | if ( ! check_ajax_referer( sprintf( 'slm_delete_domain_lic_%s_id_%s', $lic_id, $domain_id ), false, false ) ) { 71 | wp_send_json( $out ); 72 | } 73 | 74 | do_action( 'slm_before_registered_domain_delete', $domain_id ); 75 | 76 | $wpdb->query( $wpdb->prepare( "DELETE FROM $reg_table WHERE id=%d", $domain_id ) ); //phpcs:ignore 77 | 78 | $out['status'] = 'success'; 79 | $out = apply_filters( 'slm_registered_domain_delete_response', $out ); 80 | 81 | wp_send_json( $out ); 82 | } 83 | --------------------------------------------------------------------------------