Commit b0af91bd2b8c738a038369ed98712a952439cee8

Authored by ezequiel
1 parent 306dd675
Exists in master

remivido alguns bugs e feito atualizaçoes

install/inno setup/user_install.iss
... ... @@ -15,7 +15,7 @@
15 15  
16 16 [Setup]
17 17 AppId= {{84B73167-EF7F-42BB-9CCD-E1A8E2C53659-vlibras}
18   -;AppId={{B3EAE3FB-FD9B-4877-8430-B7F5C2940EC2}
  18 +
19 19 AppName={#MyAppName}
20 20 AppVersion={#MyAppVersion}
21 21 AppPublisher={#MyAppPublisher}
... ... @@ -44,12 +44,10 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
44 44 Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; OnlyBelowVersion: 0,6.1
45 45  
46 46 [Files]
47   - ;Source: itdownload.dll; Flags: dontcopy; DestDir: {tmp}
48   - ;Source: "Player\*"; DestDir: "{app}\Player"; Flags: ignoreversion recursesubdirs createallsubdirs;
49   - ;Source: "wx_3.0.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall;
50   - Source: "python-2.7.9.msi"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall;
51   - Source: "user_install\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs;
52   - Source: "required\*"; DestDir: "{tmp}\required"; Flags: ignoreversion recursesubdirs createallsubdirs deleteafterinstall
  47 +
  48 +Source: "python-2.7.9.msi"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall;
  49 +Source: "user_install\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs;
  50 +Source: "required\*"; DestDir: "{tmp}\required"; Flags: ignoreversion recursesubdirs createallsubdirs deleteafterinstall
53 51  
54 52  
55 53 [Icons]
... ... @@ -63,14 +61,38 @@ Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Fil
63 61  
64 62 Filename: msiexec ; Flags: runhidden; Parameters: /i {tmp}\python-2.7.9.msi /passive; StatusMsg: Instalando python-2.7.9...
65 63 Filename: {tmp}\required\user_install.bat; Flags: runhidden; StatusMsg: Instalando dependências...
66   -;Filename: {tmp}\wx_3.0.exe; Flags: runhidden; Parameters: /VERYSILENT /SUPPRESSMSGBOXES /NORESTART; StatusMsg: Instalando wx
67   -;Filename: {app}\update\bin\writeSucess.exe; Flags: runhidden; StatusMsg: Finalizando
68   -;Filename: {app}\update\bin\vlibrasDictUp.exe; Flags: runhidden; StatusMsg: Instalando atualização
  64 +
69 65  
70 66  
71 67  
72 68 [Code]
73 69  
  70 +
  71 +function InitializeSetup(): Boolean;
  72 +var
  73 + sPrevPath: String;
  74 + sPrevID: String;
  75 + ErrorCode: Integer;
  76 + MyProgChecked: Boolean;
  77 +begin
  78 + MyProgChecked:= True;
  79 +// verifica se existe uma instalação anterior e desinstala
  80 +if (FileExists('C:\vlibras-libs\unins000.exe')) then
  81 + if MsgBox( 'Existe uma versão anterior instalada neste computador. Será necessário remové-la antes de proceguir.', mbInformation, MB_okcancel) = idok then
  82 + begin
  83 + ShellExec('', ExpandConstant('C:\vlibras-libs\unins000.exe'), '/SILENT', '', SW_SHOW, ewNoWait, ErrorCode);
  84 +
  85 + end
  86 + else
  87 + begin
  88 + MsgBox('O VLibras Não será instalado!', mbInformation, MB_OK);
  89 + MyProgChecked:= False;
  90 + end;
  91 +
  92 + Result:= MyProgChecked;
  93 + end;
  94 +
  95 +
74 96 procedure CurStepChanged(CurStep: TSetupStep);
75 97  
76 98 var
... ... @@ -79,16 +101,14 @@ begin
79 101  
80 102 if CurStep = ssDone then
81 103 begin
  104 + DelTree('C:\vlibras-libs', True, True, True);
82 105 //chama o instalador baixado
83   - if not ShellExec('', ExpandConstant('{app}\update\bin\DicionarioUpdate.exe'), '', '', SW_SHOW, ewNoWait, ErrorCode) then
  106 + if not ShellExec('', ExpandConstant('{app}\update\bin\DicionarioUp.exe'), '', '', SW_SHOW, ewNoWait, ErrorCode) then
84 107 begin
85   - MsgBox('Houve um erro ao Instalar Dicionário ', mbError, MB_OK);
  108 + MsgBox('O VLibras foi instalado com sucesso, porém o Dicionário não foi instalado. Você poderá utilizar o VLibras Sem o Dicioário. Tente atualizar o programa para que o Dicionário seja instalado. ', mbError, MB_OK);
86 109 end;
87 110 end;
88 111  
89   -
90   -
91   -
92 112  
93 113 end;
94 114  
... ...
plugin/corePlugin.cpp
... ... @@ -8,79 +8,21 @@
8 8 #include "corePlugin.h"
9 9 #include <time.h>
10 10  
11   -
12 11 using namespace std;
13 12  
14   - ofstream logfile;
15   -
16   -
17   -//Assinatura do método itd_downloadfile utilizado na dll
18   -typedef int (WINAPI*download)(char * arg1, char * arg2);
19   -download itd_downloadfile;
20   -
21   -//usado para representar as versoes tanto da api quanto local
22   -typedef struct Versions
23   -{
24   - char versionDicionario[7]={'0','0','0','0','0','0','\0'};
25   - char versionPlayer[4]={'0','0','0','\0'};
26   -} Version;
27   -
28   -// usado para carregar os jsons de versoes
29   -Version loadVersion(char* pPathTempJson)
30   -{
31   - Version version;
32   - string line_in_str;
33   - ifstream file_versionApi;
34   - int i;
35   - try
36   - {
37   - file_versionApi.open(pPathTempJson);
38   - while ( getline (file_versionApi, line_in_str) )
39   - {
40   - if(strstr(line_in_str.c_str(), "playerVersion")){
41   - i = 0;
42   - for (char & c : line_in_str)
43   - if(isdigit(c))
44   - version.versionPlayer[i++]=c;
45   - version.versionPlayer[i]='\0';
46   - }
47   - else if(strstr(line_in_str.c_str(), "dictionaryVersion")){
48   -
49   - i = 0;
50   - for (char & c : line_in_str)
51   - if(isdigit(c))
52   - version.versionDicionario[i++]=c;
53   - version.versionDicionario[i]='\0';
54   - }
55   - }
56   - file_versionApi.close();
57   - }
58   - catch (exception e)
59   - {
60   -
61   - }
62   - return version;
63   -}
64   -
65 13  
66 14 extern "C"
67 15 {
68   -
  16 +
  17 +
69 18 EXPORT_API int coreInitialize()
70 19 {
71 20 //Objeto usado para traduzir
72 21 tradutor = new PyTradutor();
73   - update = new VlibrasUpdate();
  22 + update = new PyVlibrasUpdate();
74 23 //Objeto usado para copiar texto da área de transferência
75 24 clipboard.bdragOn();
76   - logfile.open ("C:\\VLibras\\update\\log.txt");
77   - pPathTempJson ="c:\\VLibras\\update\\VLibrasVersionApi.json";
78   - pPathVlibrasJson = "c:\\VLibras\\version.json";
79   - //Carrega a dll
80   - hDLL1 = LoadLibrary("c:\\VLibras\\update\\plugins\\itdownload.dll");
81   - //Relaciona método local com o método implementado na dll
82   - itd_downloadfile=(download)GetProcAddress((HMODULE)hDLL1, "itd_downloadfile");
83   -
  25 +
84 26 return 1;
85 27 }
86 28  
... ... @@ -96,7 +38,7 @@ Version loadVersion(char* pPathTempJson)
96 38  
97 39 EXPORT_API int coreUpdateInstall_player()
98 40 {
99   - update->install("C:\\VLibras\\update\\bin\\PlayerUpdate.exe","NULL");
  41 + update->install("c:\\VLibras\\update\\bin\\PlayerUp.exe","NULL");
100 42  
101 43 return 1;
102 44 }
... ... @@ -104,7 +46,7 @@ Version loadVersion(char* pPathTempJson)
104 46  
105 47 EXPORT_API int coreUpdateInstall_dict()
106 48 {
107   - update->install("C:\\VLibras\\update\\bin\\DicionarioUpdate.exe","NULL");
  49 + update->install("c:\\VLibras\\update\\bin\\DicionarioUp.exe","NULL");
108 50  
109 51 return 1;
110 52 }
... ... @@ -112,50 +54,37 @@ Version loadVersion(char* pPathTempJson)
112 54  
113 55 EXPORT_API int coreUpdateCheck()
114 56 {
115   -
116   - if (!hDLL1){
117   - logfile <<__TIMESTAMP__<< " --> Não carregou dll itdownload.dll.\n";
118   - return -1;
119   - }
120   -
121   - //faz download do json de versao
122   - int codDownload = itd_downloadfile("http://vlibras.lavid.ufpb.br/api/dicionario/0.0.0_0.0.0?type=json",pPathTempJson);
123   -
124   - clock_t time_end;
  57 +
  58 + string line_in_str;
  59 + ifstream file_version;
  60 + int return_int = -1;
  61 + try
  62 + {
  63 + update->checkExe("c:\\VLibras\\update\\bin\\checkVersion.exe","check");
  64 +
  65 + clock_t time_end;
125 66 time_end = clock() + 3000 * CLOCKS_PER_SEC/1000;
126 67 while (clock() < time_end);
127   -
128   - //verifica se existe os dois arquivos de versao
129   - if(!ifstream(pPathTempJson) || !ifstream(pPathVlibrasJson) || (codDownload > 0 )){
130   -
131   - logfile <<__TIMESTAMP__ <<" --> codDownload: "<<codDownload<<".\n";
132   - //return -1;
133   - }
134   -
135   - Version versionApi = loadVersion(pPathTempJson);
136   - Version versionLocal = loadVersion(pPathVlibrasJson);
137   -
138   - // compara as versoes (return '0' para nao tem attualizacao, '1' para player e '2' para dicionario)
139   - if(atoi(versionApi.versionPlayer)> atoi(versionLocal.versionPlayer))
140   - return 1;
141   - else if(atoi(versionApi.versionDicionario)> atoi(versionLocal.versionDicionario))
142   - return 2;
143   - else
144   - return 0;
145   - logfile <<__TIMESTAMP__ <<" --> codDownload2: "<<codDownload<<".\n";
146   -
147   -
  68 +
  69 +
  70 + file_version.open("c:\\VLibras\\update\\version\\version.txt");
148 71  
149   - return 0;
  72 + getline(file_version, line_in_str);
  73 + file_version.close();
  74 + return_int = atoi(line_in_str.c_str());
  75 +
  76 + return return_int;
  77 + }
  78 + catch (exception e)
  79 + {
  80 + return -1;
  81 + }
  82 + return return_int;
150 83 }
151 84  
152 85 EXPORT_API int coreFinalize()
153 86 {
154   -
155   - logfile.close();
156   - clipboard.bdragOff();
157   - //Libera dll
158   - FreeLibrary((HMODULE)hDLL1);
  87 + clipboard.bdragOff();
159 88 delete tradutor;
160 89 delete update;
161 90 return 1;
... ...
plugin/corePlugin.h
... ... @@ -21,11 +21,9 @@ VLibras-Core
21 21  
22 22 #include "pyClip.h"
23 23 #include "pyTradutor.h"
24   -#include "vlibrasUpdate.h"
  24 +#include "pyVlibrasUpdate.h"
25 25 #include <fstream>
26 26 #include <string>
27   -#include <cstdlib>
28   -
29 27  
30 28  
31 29 using namespace std;
... ... @@ -40,14 +38,7 @@ extern &quot;C&quot;
40 38 PyClip clipboard;
41 39  
42 40 //Usado para verificar se existe atualização
43   - VlibrasUpdate *update;
44   -
45   - HINSTANCE hDLL1;
46   -
47   - char* pPathTempJson;
48   -
49   - char* pPathVlibrasJson;
50   -
  41 + PyVlibrasUpdate *update;
51 42  
52 43 //Inicializa Objetos
53 44 EXPORT_API int coreInitize(void);
... ...
update/DownloadVlibrasDicionario.iss
... ... @@ -3,7 +3,7 @@
3 3 #define MyAppVersion "3.0.0"
4 4 #define MyAppPublisher "LAViD"
5 5 #define MyAppURL "http://vlibrasplayer.lavid.ufpb.br"
6   -#define MyAppExeName "VlibrasDicionario.exe"
  6 +#define MyAppExeName "DicionarioUpdate.exe"
7 7  
8 8  
9 9  
... ... @@ -20,7 +20,7 @@ DefaultDirName={sd}\VLibras\update
20 20 DisableDirPage=yes
21 21 DisableWelcomePage=yes
22 22 DefaultGroupName={#MyAppName}
23   -OutputBaseFilename=DicionarioUpdate
  23 +OutputBaseFilename=DicionarioUp
24 24 DisableProgramGroupPage=yes
25 25 DisableFinishedPage=no
26 26 OutputDir="DicionaryUpdate"
... ... @@ -47,7 +47,7 @@ Source: it_download\languages\itd_ptbr.ini; Flags: dontcopy
47 47 ErrorJson=A {#MyAppName} não conseguiu conexão com a internet.%nFavor verifique sua conexão e tente novamente.%n%n
48 48 DownloadFinalizado=A nova versão do VLibras foi baixado com sucesso .%nSiga os proximos passos para instalar essa nova versão em seu computador.%n%n
49 49 FinalizarApp=O instalador de atualização será encerrado.
50   - VersaoJaAtualizada=Não existe {#MyAppName} disponível%n Sua versão Já está atualizada!%n%n
  50 + VersaoJaAtualizada=Não há novas atualizações.%n%n
51 51  
52 52  
53 53 [Code]
... ...
update/DownloadVlibrasPlayer.iss
... ... @@ -23,7 +23,7 @@ DefaultGroupName={#MyAppName}
23 23 OutputBaseFilename=PlayerUpdate
24 24 DisableProgramGroupPage=yes
25 25 DisableFinishedPage=yes
26   -OutputDir="PlayerUpdate"
  26 +OutputDir="PlayerUp"
27 27 SetupIconFile="icon\icon_vlibras.ico"
28 28 Compression=lzma
29 29 SolidCompression=yes
... ...
update/checkVersion.cpp 0 → 100644
... ... @@ -0,0 +1,133 @@
  1 +
  2 +#include <time.h>
  3 +#include <fstream>
  4 +#include <string>
  5 +#include <cstdlib>
  6 +#include <IOSTREAM>
  7 +#include <windows.h>
  8 +#include <thread>
  9 +using namespace std;
  10 +
  11 +HINSTANCE hDLL1;
  12 +char* pPathTempJson;
  13 +char* pPathVlibrasJson;
  14 +int codDownload = -1;
  15 +
  16 +//Assinatura do método itd_downloadfile utilizado na dll
  17 +typedef int (WINAPI*download)(char * arg1, char * arg2);
  18 +download itd_downloadfile;
  19 +
  20 +ofstream versionFileCheck;
  21 +
  22 +
  23 +
  24 +//usado para representar as versoes tanto da api quanto local
  25 +typedef struct Versions
  26 +{
  27 + char versionDicionario[7]={'0','0','0','0','0','0','\0'};
  28 + char versionPlayer[4]={'0','0','0','\0'};
  29 +} Version;
  30 +
  31 +// usado para carregar os jsons de versoes
  32 +Version loadVersion(char* pPathTempJson)
  33 +{
  34 + Version version;
  35 + string line_in_str;
  36 + ifstream file_versionApi;
  37 +
  38 + int i;
  39 + try
  40 + {
  41 + file_versionApi.open(pPathTempJson);
  42 + while ( getline (file_versionApi, line_in_str) )
  43 + {
  44 + if(strstr(line_in_str.c_str(), "playerVersion")){
  45 + i = 0;
  46 + for (char & c : line_in_str)
  47 + if(isdigit(c))
  48 + version.versionPlayer[i++]=c;
  49 + version.versionPlayer[i]='\0';
  50 + }
  51 + else if(strstr(line_in_str.c_str(), "dictionaryVersion")){
  52 +
  53 + i = 0;
  54 + for (char & c : line_in_str)
  55 + if(isdigit(c))
  56 + version.versionDicionario[i++]=c;
  57 + version.versionDicionario[i]='\0';
  58 + }
  59 + }
  60 + file_versionApi.close();
  61 + }
  62 + catch (exception e)
  63 + {
  64 +
  65 + }
  66 + return version;
  67 +}
  68 +
  69 +void downloadFileJson(){
  70 +
  71 + codDownload = itd_downloadfile("http://vlibras.lavid.ufpb.br/api/dicionario/0.0.0_0.0.0?type=json",pPathTempJson);
  72 +}
  73 +
  74 +
  75 +
  76 +int main(){
  77 +
  78 + versionFileCheck.open ("c:\\VLibras\\update\\version\\version.txt");
  79 +
  80 + pPathTempJson ="C:\\VLibras\\update\\download\\VLibrasVersionApi.json";
  81 + pPathVlibrasJson = "c:\\VLibras\\version.json";
  82 + //Carrega a dll
  83 + hDLL1 = LoadLibrary("c:\\VLibras\\update\\plugins\\itdownload.dll");
  84 + //Relaciona método local com o método implementado na dll
  85 + itd_downloadfile=(download)GetProcAddress((HMODULE)hDLL1, "itd_downloadfile");
  86 +
  87 + if (hDLL1){
  88 +
  89 + //faz download do json de versao
  90 + thread tDownloadFileJson(downloadFileJson);
  91 +
  92 + clock_t time_end;
  93 + time_end = clock() + 3000 * CLOCKS_PER_SEC/1000;
  94 + while (clock() < time_end);
  95 +
  96 + if(codDownload == -1){
  97 + versionFileCheck << "-1";
  98 + goto erro;
  99 + }
  100 + tDownloadFileJson.join();
  101 +
  102 + //verifica se existe os dois arquivos de versao
  103 + if(!ifstream(pPathTempJson) || !ifstream(pPathVlibrasJson) || (codDownload > 0 )){
  104 +
  105 + versionFileCheck << "-1";
  106 + goto erro;
  107 + }
  108 +
  109 + Version versionApi = loadVersion(pPathTempJson);
  110 + Version versionLocal = loadVersion(pPathVlibrasJson);
  111 +
  112 + // compara as versoes (return '0' para nao tem attualizacao, '1' para player e '2' para dicionario)
  113 + if(atoi(versionApi.versionPlayer)> atoi(versionLocal.versionPlayer))
  114 + versionFileCheck << "1";
  115 + else if(atoi(versionApi.versionDicionario)> atoi(versionLocal.versionDicionario))
  116 + versionFileCheck << "2";
  117 + else
  118 + versionFileCheck << "0";
  119 + }
  120 + else
  121 + versionFileCheck << "-1";
  122 +
  123 +
  124 + erro:
  125 +
  126 +
  127 + versionFileCheck.close();
  128 +
  129 + //Libera dll
  130 + FreeLibrary((HMODULE)hDLL1);
  131 + return 1;
  132 +
  133 +}
0 134 \ No newline at end of file
... ...
update/include/pyVlibrasUpdate.h 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +//*****************************************************************
  2 +/*
  3 +
  4 +Copyright (c) 2015 Ezequiel Silva
  5 +VLibras-Core group at LAViD, Federal University of Paraiba
  6 +*/
  7 +//*****************************************************************
  8 +
  9 +/**
  10 +* \file pyVlibrasUpdate.h
  11 +* \authors Ezequiel Silva
  12 +* \date Setembro 2015
  13 +*/
  14 +#ifndef _PHVLIBRASUPDATE_H
  15 +#define _PHVLIBRASUPDATE_H
  16 +
  17 +#include <windows.h>
  18 +
  19 +/** \brief Classe para execução do Vlibras Update.
  20 +*
  21 +*/
  22 +class PyVlibrasUpdate
  23 +{
  24 +
  25 + public:
  26 + int install(char* strFunct, char* strstrParams);
  27 + void checkExe(char* strFunct, char* strstrParams);
  28 +
  29 +};
  30 +
  31 +#endif
0 32 \ No newline at end of file
... ...
update/src/pyVlibrasUpdate.cpp 0 → 100644
... ... @@ -0,0 +1,103 @@
  1 +
  2 +/**
  3 +* \file pyVlibrasUpdate.cpp
  4 +* \authors Ezequiel Silva
  5 +* \date outubro 2015
  6 +*/
  7 +
  8 +#include "pyVlibrasUpdate.h"
  9 +
  10 +
  11 +void PyVlibrasUpdate::checkExe(char* strFunct, char* strstrParams)
  12 +{
  13 +
  14 + STARTUPINFO StartupInfo;
  15 + PROCESS_INFORMATION ProcessInfo;
  16 + char Args[4096];
  17 + char *pEnvCMD = NULL;
  18 + char *pDefaultCMD = "CMD.EXE";
  19 + ULONG rc;
  20 +
  21 + memset(&StartupInfo, 0, sizeof(StartupInfo));
  22 + StartupInfo.cb = sizeof(STARTUPINFO);
  23 + StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  24 + StartupInfo.wShowWindow = SW_HIDE;
  25 +
  26 + Args[0] = 0;
  27 +
  28 + pEnvCMD = getenv("COMSPEC");
  29 +
  30 + if(pEnvCMD){
  31 +
  32 + strcpy(Args, pEnvCMD);
  33 + }
  34 + else{
  35 + strcpy(Args, pDefaultCMD);
  36 + }
  37 +
  38 + // "/c" option - Do the command then terminate the command window
  39 + strcat(Args, " /c ");
  40 + //the application you would like to run from the command window
  41 + strcat(Args, strFunct);
  42 + strcat(Args, " ");
  43 + //the parameters passed to the application being run from the command window.
  44 + strcat(Args, strstrParams);
  45 +
  46 + if (!CreateProcess( NULL, Args, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo))
  47 + {
  48 + return;
  49 + }
  50 +
  51 + WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
  52 + if(!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
  53 + rc = 0;
  54 +
  55 + CloseHandle(ProcessInfo.hThread);
  56 + CloseHandle(ProcessInfo.hProcess);
  57 +
  58 +
  59 +}
  60 +
  61 +int PyVlibrasUpdate::install(char* strFunct, char* strstrParams)
  62 +{
  63 +
  64 + STARTUPINFO StartupInfo;
  65 + PROCESS_INFORMATION ProcessInfo;
  66 + char Args[4096];
  67 + char *pEnvCMD = NULL;
  68 + char *pDefaultCMD = "CMD.EXE";
  69 +
  70 + memset(&StartupInfo, 0, sizeof(StartupInfo));
  71 + StartupInfo.cb = sizeof(STARTUPINFO);
  72 + StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  73 + StartupInfo.wShowWindow = SW_HIDE;
  74 +
  75 + Args[0] = 0;
  76 +
  77 + pEnvCMD = getenv("COMSPEC");
  78 +
  79 + if(pEnvCMD){
  80 +
  81 + strcpy(Args, pEnvCMD);
  82 + }
  83 + else{
  84 + strcpy(Args, pDefaultCMD);
  85 + }
  86 +
  87 + // "/c" option - Do the command then terminate the command window
  88 + strcat(Args, " /c ");
  89 + //the application you would like to run from the command window
  90 + strcat(Args, strFunct);
  91 + strcat(Args, " ");
  92 + //the parameters passed to the application being run from the command window.
  93 + strcat(Args, strstrParams);
  94 +
  95 + if (!CreateProcess( NULL, Args, NULL, NULL, FALSE,CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo))
  96 + {
  97 + return -1;
  98 + }
  99 +
  100 + return -1;
  101 +
  102 +}
  103 +
... ...