medicafe 0.250529.2__py3-none-any.whl → 0.250610.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of medicafe might be problematic. Click here for more details.

@@ -13,7 +13,19 @@ downloaded_emails_file = os.path.join(local_storage_path, 'downloaded_emails.txt
13
13
  server_port = 8000
14
14
  cert_file = 'server.cert'
15
15
  key_file = 'server.key'
16
- openssl_cnf = 'MediLink\\openssl.cnf' # This file needs to be located in the same place as where MediCafe is run from (so MediBot folder?)
16
+ # Try to find openssl.cnf in various locations
17
+ openssl_cnf = 'MediLink\\openssl.cnf'
18
+ if not os.path.exists(openssl_cnf):
19
+ log("Could not find openssl.cnf at: " + os.path.abspath(openssl_cnf))
20
+ # Try one directory up
21
+ parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
22
+ alternative_path = os.path.join(parent_dir, 'MediBot', 'openssl.cnf')
23
+ log("Trying alternative path: " + alternative_path)
24
+ if os.path.exists(alternative_path):
25
+ openssl_cnf = alternative_path
26
+ log("Found openssl.cnf at: " + openssl_cnf)
27
+ else:
28
+ log("Could not find openssl.cnf at alternative path either")
17
29
 
18
30
  httpd = None # Global variable for the HTTP server
19
31
  shutdown_event = Event() # Event to signal shutdown
@@ -321,13 +333,40 @@ class RequestHandler(BaseHTTPRequestHandler):
321
333
  def generate_self_signed_cert(cert_file, key_file):
322
334
  log("Checking if certificate file exists: " + cert_file)
323
335
  log("Checking if key file exists: " + key_file)
324
- if not os.path.exists(cert_file) or not os.path.exists(key_file):
336
+
337
+ # Check if certificate exists and is not expired
338
+ cert_needs_regeneration = True
339
+ if os.path.exists(cert_file):
340
+ try:
341
+ # Check certificate expiration
342
+ check_cmd = ['openssl', 'x509', '-in', cert_file, '-checkend', '86400', '-noout'] # Check if expires in next 24 hours
343
+ result = subprocess.call(check_cmd)
344
+ if result == 0:
345
+ log("Certificate is still valid")
346
+ cert_needs_regeneration = False
347
+ else:
348
+ log("Certificate is expired or will expire soon")
349
+ # Delete expired certificate and key files
350
+ try:
351
+ if os.path.exists(cert_file):
352
+ os.remove(cert_file)
353
+ log("Deleted expired certificate file: {}".format(cert_file))
354
+ if os.path.exists(key_file):
355
+ os.remove(key_file)
356
+ log("Deleted expired key file: {}".format(key_file))
357
+ except Exception as e:
358
+ log("Error deleting expired certificate files: {}".format(e))
359
+ except Exception as e:
360
+ log("Error checking certificate expiration: {}".format(e))
361
+
362
+ if cert_needs_regeneration:
325
363
  log("Generating self-signed SSL certificate...")
326
364
  cmd = [
327
365
  'openssl', 'req', '-config', openssl_cnf, '-nodes', '-new', '-x509',
328
366
  '-keyout', key_file,
329
367
  '-out', cert_file,
330
- '-days', '365'
368
+ '-days', '365',
369
+ '-sha256' # Use SHA-256 for better security
331
370
  #'-subj', '/C=US/ST=...' The openssl.cnf file contains default values for these fields, but they can be overridden by the -subj option.
332
371
  ]
333
372
  try:
@@ -336,7 +375,14 @@ def generate_self_signed_cert(cert_file, key_file):
336
375
  log("Command finished with result: " + str(result))
337
376
  if result != 0:
338
377
  raise RuntimeError("Failed to generate self-signed certificate")
339
- log("Self-signed SSL certificate generated.")
378
+
379
+ # Verify the certificate was generated correctly
380
+ verify_cmd = ['openssl', 'x509', '-in', cert_file, '-text', '-noout']
381
+ verify_result = subprocess.call(verify_cmd)
382
+ if verify_result != 0:
383
+ raise RuntimeError("Generated certificate verification failed")
384
+
385
+ log("Self-signed SSL certificate generated and verified successfully.")
340
386
  except Exception as e:
341
387
  log("Error generating self-signed certificate: {}".format(e))
342
388
  raise
MediLink/openssl.cnf ADDED
@@ -0,0 +1,29 @@
1
+ # OpenSSL configuration file for creating a self-signed certificate
2
+
3
+ [ req ]
4
+ default_bits = 2048
5
+ default_keyfile = server.key
6
+ distinguished_name = req_distinguished_name
7
+ x509_extensions = v3_req
8
+ string_mask = utf8only
9
+ prompt = no
10
+
11
+ [ req_distinguished_name ]
12
+ countryName = US
13
+ stateOrProvinceName = California
14
+ localityName = San Francisco
15
+ organizationName = MediLink
16
+ organizationalUnitName = Development
17
+ commonName = localhost
18
+ emailAddress = admin@medilink.local
19
+
20
+ [ v3_req ]
21
+ basicConstraints = CA:FALSE
22
+ keyUsage = nonRepudiation, digitalSignature, keyEncipherment
23
+ subjectAltName = @alt_names
24
+ extendedKeyUsage = serverAuth, clientAuth
25
+
26
+ [ alt_names ]
27
+ DNS.1 = localhost
28
+ IP.1 = 127.0.0.1
29
+ DNS.2 = 127.0.0.1
MediLink/webapp.html ADDED
@@ -0,0 +1,473 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Select an Email</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Montserrat:wght@400;600&display=swap" rel="stylesheet">
8
+ <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.12.1/polyfill.min.js"></script> -->
9
+ <style>
10
+
11
+ :root {
12
+ --espresso-dark: #3B2323; /* Darkened color */
13
+ --espresso-medium: #4E3B3B; /* Adjusted for a more coffee-like tone */
14
+ --espresso-light: #7A4B4B; /* Darkened color */
15
+ --cream: #EDE0D4; /* Darkened color */
16
+ --background: #dcd6c9; /* Darkened color */
17
+ --accent: #C65D1E; /* Darkened color */
18
+ --error-red: #D9534F;
19
+ --loading-orange: #F0AD4E;
20
+ --text-color: #222222; /* Darkened color */
21
+ --button-hover: #4B2E2E; /* Darkened color */
22
+ }
23
+
24
+ * {
25
+ box-sizing: border-box;
26
+ }
27
+
28
+ body {
29
+ font-family: 'Montserrat', sans-serif;
30
+ margin: 0;
31
+ padding: 0;
32
+ background-color: var(--background);
33
+ color: var(--text-color);
34
+ display: flex;
35
+ justify-content: center;
36
+ align-items: center;
37
+ min-height: 100vh;
38
+ }
39
+
40
+ main {
41
+ width: 90%;
42
+ max-width: 800px; /* Reduced max-width */
43
+ margin: 20px auto; /* Reduced margin */
44
+ padding: 20px; /* Reduced padding */
45
+ background: var(--cream);
46
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Reduced shadow */
47
+ border-radius: 8px; /* Reduced border-radius */
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 20px; /* Reduced gap */
51
+ }
52
+
53
+ h1 {
54
+ text-align: center;
55
+ font-family: 'Roboto', sans-serif;
56
+ font-weight: 600; /* Reduced font weight */
57
+ color: var(--espresso-dark);
58
+ margin-bottom: 15px; /* Reduced margin */
59
+ font-size: 1.8em; /* Reduced font size */
60
+ position: relative;
61
+ }
62
+
63
+ h1::after {
64
+ content: '';
65
+ display: block;
66
+ width: 50px; /* Reduced width */
67
+ height: 3px; /* Reduced height */
68
+ background-color: var(--espresso-medium);
69
+ margin: 8px auto 0; /* Reduced margin */
70
+ border-radius: 2px;
71
+ }
72
+
73
+ ul {
74
+ list-style-type: none;
75
+ padding: 0;
76
+ margin: 0;
77
+ display: flex;
78
+ flex-direction: column;
79
+ gap: 10px; /* Reduced gap */
80
+ }
81
+
82
+ li {
83
+ background-color: var(--espresso-light);
84
+ padding: 8px; /* Reduced padding */
85
+ border-radius: 6px; /* Reduced border-radius */
86
+ font-size: 1.1em; /* Reduced font size */
87
+ }
88
+
89
+ /* New styling for docxEmailList */
90
+ #docxEmailList li {
91
+ background-color: transparent; /* Plain background */
92
+ padding: 8px; /* Keep padding */
93
+ border: none; /* No border */
94
+ box-shadow: none; /* No shadow */
95
+ transition: none; /* No transition */
96
+ }
97
+
98
+ button {
99
+ width: 100%;
100
+ padding: 4px 8px; /* Reduced padding */
101
+ background-color: var(--espresso-medium);
102
+ color: #ffffff;
103
+ border: none;
104
+ border-radius: 6px; /* Reduced border-radius */
105
+ cursor: pointer;
106
+ font-size: 1.1em; /* Reduced font size */
107
+ font-weight: 500; /* Reduced font weight */
108
+ transition: background-color 0.3s, transform 0.2s;
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ margin-bottom: 8px; /* Reduced margin */
113
+ }
114
+
115
+ button:hover {
116
+ background-color: var(--espresso-dark);
117
+ transform: scale(1.01); /* Reduced scale effect */
118
+ }
119
+
120
+ .error-message {
121
+ color: var(--error-red);
122
+ text-align: center;
123
+ font-weight: bold;
124
+ margin-top: 15px; /* Reduced margin */
125
+ padding: 8px; /* Reduced padding */
126
+ border: 1px solid var(--error-red);
127
+ border-radius: 6px;
128
+ background-color: #fdecea;
129
+ }
130
+
131
+ .loading-message {
132
+ color: var(--loading-orange);
133
+ text-align: center;
134
+ font-weight: bold;
135
+ margin-top: 15px; /* Reduced margin */
136
+ padding: 8px; /* Reduced padding */
137
+ border: 1px solid var(--loading-orange);
138
+ border-radius: 6px;
139
+ background-color: #fff4e6;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ gap: 8px; /* Reduced gap */
144
+ }
145
+
146
+ /* Responsive Design */
147
+ @media (max-width: 600px) {
148
+ main {
149
+ padding: 15px; /* Reduced padding */
150
+ }
151
+
152
+ h1 {
153
+ font-size: 1.1em; /* Reduced font size */
154
+ }
155
+
156
+ button {
157
+ font-size: 1em; /* Reduced font size */
158
+ padding: 4px 6px; /* Reduced padding */
159
+ }
160
+ }
161
+ </style>
162
+ </head>
163
+ <body>
164
+ <main>
165
+ <!-- <h1>Please Select the Correct Email</h1> -->
166
+ <!-- <ul id="emailList"></ul> -->
167
+
168
+ <h1>New Surgery Schedules</h1>
169
+ <ul id="docxEmailList" style="color: var(--text-color);"></ul> <!-- Static list with black text -->
170
+
171
+ <div id="errorMessage" class="error-message" style="display:none;"></div>
172
+ <div id="loadingMessage" class="loading-message" style="display:none;">
173
+ <span>⏳</span> Loading DOCX results...
174
+ </div>
175
+ </main>
176
+ <script>
177
+ document.addEventListener("DOMContentLoaded", () => {
178
+ console.log("Document ready, initializing flows...");
179
+ // initializeEmailListFlow();
180
+ initializeDocxEmailListFlow();
181
+ });
182
+
183
+ /**
184
+ * Initializes the Email List Flow.
185
+ * Fetches email subjects and builds the email list.
186
+ */
187
+ async function initializeEmailListFlow() {
188
+ try {
189
+ console.log("Initializing Email List Flow...");
190
+ const subjectsResponse = await fetchEmailSubjects();
191
+ console.log("Email subjects fetched:", subjectsResponse);
192
+ buildEmailList(subjectsResponse);
193
+ } catch (error) {
194
+ console.error("Error initializing Email List Flow:", error);
195
+ displayErrorMessage("Failed to load email subjects.");
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Initializes the DOCX Email List Flow.
201
+ * Initiates DOCX processing and fetches results upon completion.
202
+ */
203
+ async function initializeDocxEmailListFlow() {
204
+ try {
205
+ console.log("Initializing DOCX Email List Flow...");
206
+ showLoadingMessage();
207
+ const processResponse = await startProcessingDocxAsync();
208
+ console.log("DOCX processing initiated:", processResponse);
209
+
210
+ if (processResponse.status === "success") {
211
+ const docxResultsResponse = await fetchDocxResults();
212
+ console.log("DOCX results fetched:", docxResultsResponse);
213
+ buildDocxList(docxResultsResponse);
214
+ } else {
215
+ console.error("DOCX processing failed:", processResponse.message);
216
+ displayErrorMessage("Failed to process DOCX attachments: " + processResponse.message);
217
+ }
218
+ hideLoadingMessage();
219
+ } catch (error) {
220
+ console.error("Error initializing DOCX Email List Flow:", error);
221
+ displayErrorMessage("Failed to process DOCX attachments.");
222
+ hideLoadingMessage();
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Fetches email subjects from the server.
228
+ * @returns {Object} The email subjects response.
229
+ */
230
+ async function fetchEmailSubjects() {
231
+ console.log("Fetching email subjects...");
232
+ return new Promise((resolve, reject) => {
233
+ google.script.run
234
+ .withSuccessHandler(response => {
235
+ console.log("Received email subjects response:", response);
236
+ resolve(response);
237
+ })
238
+ .withFailureHandler(error => {
239
+ console.error("Failed to fetch email subjects:", error);
240
+ reject(error);
241
+ })
242
+ .get_subjects();
243
+ });
244
+ }
245
+
246
+ /**
247
+ * Builds the email list UI based on fetched subjects.
248
+ * @param {Object} subjectsResponse The email subjects response.
249
+ */
250
+ function buildEmailList(subjectsResponse) {
251
+ console.log("Building email list...");
252
+ if (subjectsResponse.status === "success") {
253
+ const subjects = subjectsResponse.data;
254
+ const emailList = document.getElementById('emailList');
255
+ emailList.innerHTML = ''; // Clear existing list
256
+
257
+ subjects.forEach(subject => {
258
+ const li = document.createElement('li');
259
+ const button = document.createElement('button');
260
+ button.textContent = subject.subject;
261
+ button.addEventListener('click', () => selectEmail(subject.index));
262
+ li.appendChild(button);
263
+ emailList.appendChild(li);
264
+ });
265
+
266
+ console.log("Email list built successfully.");
267
+ } else {
268
+ console.error("Failed to retrieve email subjects:", subjectsResponse.message);
269
+ displayErrorMessage("Failed to load email subjects: " + subjectsResponse.message);
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Handles email selection by the user.
275
+ * Extracts the link from the selected email and redirects the user.
276
+ * @param {number} index The index of the selected email.
277
+ */
278
+ async function selectEmail(index) {
279
+ try {
280
+ console.log("User selected email with index:", index);
281
+ const response = await extractLinkFromEmail(index);
282
+ console.log("Link extraction response:", response);
283
+
284
+ if (response.status === "success") {
285
+ console.log("Redirecting to link:", response.data);
286
+ window.open(response.data, '_blank'); // polyfill not necessary because can't inject into the Office 365.
287
+ // window.location.href = response.data; // Open link in the same tab.
288
+ } else {
289
+ alert('Error: ' + response.message);
290
+ }
291
+ } catch (error) {
292
+ console.error("Error selecting email:", error);
293
+ alert('Failed to extract email link.');
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Extracts a link from the selected email.
299
+ * @param {number} index The index of the email to extract the link from.
300
+ * @returns {Object} The link extraction response.
301
+ */
302
+ async function extractLinkFromEmail(index) {
303
+ console.log("Extracting link from email with index:", index);
304
+ return new Promise((resolve, reject) => {
305
+ google.script.run
306
+ .withSuccessHandler(response => {
307
+ console.log("Received link extraction response:", response);
308
+ resolve(response);
309
+ })
310
+ .withFailureHandler(error => {
311
+ console.error("Failed to extract link from email:", error);
312
+ reject(error);
313
+ })
314
+ .get_link(index);
315
+ });
316
+ }
317
+
318
+ /**
319
+ * Initiates DOCX processing synchronously on the server.
320
+ * @returns {Object} The processing initiation response.
321
+ */
322
+ async function startProcessingDocxAsync() {
323
+ console.log("Starting DOCX processing...");
324
+ return new Promise((resolve, reject) => {
325
+ google.script.run
326
+ .withSuccessHandler(response => {
327
+ console.log("DOCX processing initiation response:", response);
328
+ resolve(response);
329
+ })
330
+ .withFailureHandler(error => {
331
+ console.error("Failed to initiate DOCX processing:", error);
332
+ reject(error);
333
+ })
334
+ .process_docx();
335
+ });
336
+ }
337
+
338
+ /**
339
+ * Fetches the DOCX processing results from the server.
340
+ * @returns {Object} The DOCX results response.
341
+ */
342
+ async function fetchDocxResults() {
343
+ console.log("Fetching DOCX processing results...");
344
+ return new Promise((resolve, reject) => {
345
+ google.script.run
346
+ .withSuccessHandler(response => {
347
+ console.log("Received DOCX results response:", response);
348
+ resolve(response);
349
+ })
350
+ .withFailureHandler(error => {
351
+ console.error("Failed to fetch DOCX results:", error);
352
+ reject(error);
353
+ })
354
+ .get_docx_results();
355
+ });
356
+ }
357
+
358
+ /**
359
+ * Builds the DOCX email list UI based on fetched results.
360
+ * @param {Object} docxResultsResponse The DOCX results response.
361
+ */
362
+ function buildDocxList(docxResultsResponse) {
363
+ console.log("Building DOCX email list...");
364
+ if (docxResultsResponse.status === "success") {
365
+ const { subjects, downloadLinks } = docxResultsResponse.data;
366
+ const docxList = document.getElementById('docxEmailList');
367
+ docxList.innerHTML = ''; // Clear existing list
368
+
369
+ subjects.forEach(subject => {
370
+ const li = document.createElement('li');
371
+ li.textContent = subject.subject;
372
+ docxList.appendChild(li);
373
+ });
374
+
375
+ console.log("DOCX email list built successfully.");
376
+
377
+ // **Uncomment the following line to send download links to the Python server**
378
+ sendDownloadLinksToPythonServer(downloadLinks);
379
+ } else {
380
+ console.error("Failed to retrieve DOCX results:", docxResultsResponse.message);
381
+ displayErrorMessage("Failed to load DOCX results: " + docxResultsResponse.message);
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Sends download links to the Python server for further processing.
387
+ * @param {Array} downloadLinks The list of download links.
388
+ */
389
+ async function sendDownloadLinksToPythonServer(downloadLinks) {
390
+ if (!downloadLinks || downloadLinks.length === 0) {
391
+ console.error("No download links to send.");
392
+ displayErrorMessage("No download links available to send.");
393
+ return;
394
+ }
395
+
396
+ console.log("Sending download links to Python server:", downloadLinks);
397
+ try {
398
+ const response = await fetch('https://127.0.0.1:8000/download', {
399
+ method: 'POST',
400
+ headers: {'Content-Type': 'application/json'},
401
+ body: JSON.stringify({
402
+ links: downloadLinks.map(link => ({
403
+ url: link.url,
404
+ filename: link.filename,
405
+ }))
406
+ }),
407
+ mode: 'cors' // Ensure the request includes CORS headers
408
+ });
409
+
410
+ // Log the response status and headers for debugging
411
+ console.log("Response status:", response.status);
412
+ console.log("Response headers:", response.headers);
413
+
414
+ if (!response.ok) {
415
+ const errorText = await response.text(); // Get the error message from the response
416
+ console.error('Network response was not ok:', errorText);
417
+ throw new Error(`Network response was not ok: ${response.status} - ${errorText}`);
418
+ }
419
+
420
+ const data = await response.json();
421
+ console.log("Python server response:", data);
422
+ if (data.status === 'success') {
423
+ console.log("Download links successfully sent to Python server.");
424
+ } else {
425
+ console.error("Error from Python server:", data.message);
426
+ displayErrorMessage('Error: ' + data.message);
427
+ }
428
+ } catch (error) {
429
+ console.error('Error sending download links to Python server:', error);
430
+ displayErrorMessage('Unable to send download links to the server. Error: ' + error.message);
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Delays execution for a specified number of milliseconds.
436
+ * @param {number} ms The delay duration in milliseconds.
437
+ * @returns {Promise} A promise that resolves after the delay.
438
+ */
439
+ function delay(ms) {
440
+ return new Promise(resolve => setTimeout(resolve, ms));
441
+ }
442
+
443
+ /**
444
+ * Displays an error message to the user.
445
+ * @param {string} message The error message to display.
446
+ */
447
+ function displayErrorMessage(message) {
448
+ console.error("Error:", message); // Log the error to the console
449
+ const errorDiv = document.getElementById('errorMessage');
450
+ errorDiv.textContent = message;
451
+ errorDiv.style.display = 'block';
452
+ }
453
+
454
+ /**
455
+ * Shows the loading message.
456
+ */
457
+ function showLoadingMessage() {
458
+ console.log("Showing loading message.");
459
+ const loadingDiv = document.getElementById('loadingMessage');
460
+ loadingDiv.style.display = 'block';
461
+ }
462
+
463
+ /**
464
+ * Hides the loading message.
465
+ */
466
+ function hideLoadingMessage() {
467
+ console.log("Hiding loading message.");
468
+ const loadingDiv = document.getElementById('loadingMessage');
469
+ loadingDiv.style.display = 'none';
470
+ }
471
+ </script>
472
+ </body>
473
+ </html>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: medicafe
3
- Version: 0.250529.2
3
+ Version: 0.250610.1
4
4
  Summary: MediCafe
5
5
  Home-page: https://github.com/katanada2
6
6
  Author: Daniel Vidaud
@@ -29,7 +29,7 @@ MediLink/MediLink_Decoder.py,sha256=Suw9CmUHgoe0ZW8sJP_pIO8URBrhO5FmxFF8RcUj9lI,
29
29
  MediLink/MediLink_Deductible.py,sha256=G1l7shl6uvMBO4R14CcKJ41lRW2AiR9Ahg1tHsETZzo,13490
30
30
  MediLink/MediLink_Down.py,sha256=hrDODhs-zRfOKCdiRGENN5Czu-AvdtwJj4Q7grcRXME,6518
31
31
  MediLink/MediLink_ERA_decoder.py,sha256=MiOtDcXnmevPfHAahIlTLlUc14VcQWAor9Xa7clA2Ts,8710
32
- MediLink/MediLink_Gmail.py,sha256=sfyt4g7GPhyWk6De5SxvnU4EQB-RWyvpDcrWvD7Zbzw,29317
32
+ MediLink/MediLink_Gmail.py,sha256=OYsASNgP4YSTaSnj9XZxPPiy0cw41JC-suLIgRyNrlQ,31439
33
33
  MediLink/MediLink_Mailer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  MediLink/MediLink_Parser.py,sha256=YCg2jvoJUi048GICUmP0v71b-hGqwxUQelhoi3P33i4,8128
35
35
  MediLink/MediLink_Scan.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -40,9 +40,11 @@ MediLink/MediLink_Up.py,sha256=kkBxXl1xiKiblwF4uj3r_-keLlSzNNWnu4ZbY2ipNcs,23206
40
40
  MediLink/MediLink_batch.bat,sha256=nqL5QwCLyRQFSPdv6kgtcV_cpky7FXSOWVl6OxjRXb4,118
41
41
  MediLink/Soumit_api.py,sha256=5JfOecK98ZC6NpZklZW2AkOzkjvrbYxpJpZNH3rFxDw,497
42
42
  MediLink/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ MediLink/openssl.cnf,sha256=76VdcGCykf0Typyiv8Wd1mMVKixrQ5RraG6HnfKFqTo,887
43
44
  MediLink/test.py,sha256=kSvvJRL_3fWuNS3_x4hToOnUljGLoeEw6SUTHQWQRJk,3108
44
- medicafe-0.250529.2.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
45
- medicafe-0.250529.2.dist-info/METADATA,sha256=2Z8rcfCru9dKCUFxGlDda91jEPVD0cY9t2V2MWF7o-s,5501
46
- medicafe-0.250529.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
47
- medicafe-0.250529.2.dist-info/top_level.txt,sha256=3uOwR4q_SP8Gufk2uCHoKngAgbtdOwQC6Qjl7ViBa_c,17
48
- medicafe-0.250529.2.dist-info/RECORD,,
45
+ MediLink/webapp.html,sha256=JPKT559aFVBi1r42Hz7C77Jj0teZZRumPhBev8eSOLk,19806
46
+ medicafe-0.250610.1.dist-info/LICENSE,sha256=65lb-vVujdQK7uMH3RRJSMwUW-WMrMEsc5sOaUn2xUk,1096
47
+ medicafe-0.250610.1.dist-info/METADATA,sha256=baoWulWhHJpE8qCizJ5QqsjVBLdAS2gEXUDuHlg9jrI,5501
48
+ medicafe-0.250610.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
49
+ medicafe-0.250610.1.dist-info/top_level.txt,sha256=3uOwR4q_SP8Gufk2uCHoKngAgbtdOwQC6Qjl7ViBa_c,17
50
+ medicafe-0.250610.1.dist-info/RECORD,,