1<?php
2/********************************************************************************************************************************
3*
4* LabVIEW Hacker Packet Plugin
5*
6* Written By Sammy_K
7* www.labviewhacker.com
8*
9/*******************************************************************************************************************************/
10
11
12// must be run within DokuWiki
13if(!defined('DOKU_INC')) die();
14
15if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
16require_once DOKU_PLUGIN.'syntax.php';
17
18//Include LVH Plugin Common Code
19if(!defined('LVH_COMMON'))
20{
21	define('LVH_COMMON', 'lib/plugins/lvhplugincommon.php');
22	include 'lib/plugins/lvhplugincommon.php';
23}
24
25/********************************************************************************************************************************
26* All DokuWiki plugins to extend the parser/rendering mechanism
27* need to inherit from this class
28********************************************************************************************************************************/
29class syntax_plugin_lvhpacket extends DokuWiki_Syntax_Plugin
30{
31
32	//Return Plugin Info
33	function getInfo()
34	{
35        return array('author' => 'Sammy_K',
36                     'email'  => 'sammyk.labviewhacker@gmail.com',
37                     'date'   => '2013-07-28',
38                     'name'   => 'LabVIEW Hacker Packet',
39                     'desc'   => 'Template for describing a packet',
40                     'url'    => 'www.labviewhacker.com');
41    }
42
43
44	//Set This To True To Enable Debug Strings
45	protected $lvhDebug = false;
46
47	/***************************************************************************************************************************
48	* Plugin Variables
49	***************************************************************************************************************************/
50	protected $name = '';
51	protected $description = '';
52	protected $size = '';
53	protected $format = '';
54	protected $subPackets = array();
55	protected $allPackets = array();
56
57	protected $subPacketNum = 0;
58	protected $subPacketIdNum = 0;
59	protected $subPacketValueNum = 0;
60	protected $subPacketSizeNum = 0;
61	protected $subPacketDetailsNum = 0;
62
63
64    /********************************************************************************************************************************************
65	** Plugin Configuration
66	********************************************************************************************************************************************/
67
68    function getType() { return 'protected'; }
69    function getSort() { return 32; }
70
71    function connectTo($mode) {
72        $this->Lexer->addEntryPattern('{{lvh_packet.*?(?=.*?}})',$mode,'plugin_lvhpacket');
73
74		//Add Internal Pattern Match For Product Page Elements
75		$this->Lexer->addPattern('\|.*?(?=.*?)\n','plugin_lvhpacket');
76    }
77
78    function postConnect() {
79      $this->Lexer->addExitPattern('}}','plugin_lvhpacket');
80    }
81
82	/********************************************************************************************************************************************
83	** Handle
84	********************************************************************************************************************************************/
85
86    function handle($match, $state, $pos, &$handler)
87	{
88		switch ($state)
89		{
90			case DOKU_LEXER_ENTER :
91				break;
92			case DOKU_LEXER_MATCHED :
93				//Find The Token And Value (Before '=' remove white space, convert to lower case).
94				$tokenDiv = strpos($match, '=');								//Find Token Value Divider ('=')
95				$token = strtolower(trim(substr($match, 1, ($tokenDiv - 1))));	//Everything Before '=', Remove White Space, Convert To Lower Case
96				$value = substr($match, ($tokenDiv + 1));						//Everything after '='
97				switch($token)
98				{
99					case 'name':
100						$this->name = $value;
101						break;
102					case 'description':
103						$this->description = $value;
104						break;
105					case 'size':
106						$this->size = $value;
107						break;
108					case 'format':
109						$this->format = $value;
110						break;
111					case 'subpacketid' :
112						if($this->subPacketIdNum != $this->subPacketNum)
113						{
114							//New Subpacket
115							$this->subPacketNum++;
116							$this->subPacketIdNum = $this->subPacketNum;
117							$this->subPacketValueNum = $this->subPacketNum;
118							$this->subPacketSizeNum = $this->subPacketNum;
119							$this->subPacketDetailsNum = $this->subPacketNum;
120						}
121						//Add New Subpacket ID
122						$this->subPackets[$this->subPacketNum][0] = $value;
123						$this->subPacketIdNum++;
124						break;
125					case 'subpacketsize' :
126						if($this->subPacketSizeNum != $this->subPacketNum)
127						{
128							//New Subpacket
129							$this->subPacketNum++;
130							$this->subPacketIdNum = $this->subPacketNum;
131							$this->subPacketValueNum = $this->subPacketNum;
132							$this->subPacketSizeNum = $this->subPacketNum;
133							$this->subPacketDetailsNum = $this->subPacketNum;
134						}
135						//-------Add New Subpacket Size-------//
136						//Create New Subpacket Entry If Necissary
137						if(count($this->subPackets[$this->subPacketNum]) == 0)
138						{
139							$this->subPackets[$subPacketNum][0] = '';
140						}
141						$this->subPackets[$this->subPacketNum][1] = $value;
142						$this->subPacketSizeNum++;
143						break;
144					case 'subpacketdetails':
145						if($this->subPacketDetailsNum != $this->subPacketNum)
146						{
147							//New Subpacket
148							$this->subPacketNum++;
149							$this->subPacketIdNum = $this->subPacketNum;
150							$this->subPacketValueNum = $this->subPacketNum;
151							$this->subPacketSizeNum = $this->subPacketNum;
152							$this->subPacketDetailsNum = $this->subPacketNum;
153						}
154						//Add New Subpacket Size
155						//Create New Subpacket Entry If Necissary
156						if(count($this->subPackets[$this->subPacketNum]) == 0)
157						{
158							$this->subPackets[$this->subPacketNum][0] = '';
159						}
160						$this->subPackets[$this->subPacketNum][2] = $value;
161						$this->subPacketDetailsNum++;
162						break;
163					case 'subpacketvalue' :
164						if($this->subPacketValueNum != $this->subPacketNum)
165						{
166							//New Subpacket
167							$this->subPacketNum++;
168							$this->subPacketIdNum = $this->subPacketNum;
169							$this->subPacketValueNum = $this->subPacketNum;
170							$this->subPacketSizeNum = $this->subPacketNum;
171							$this->subPacketDetailsNum = $this->subPacketNum;
172						}
173						//Add New Subpacket Size
174						//Create New Subpacket Entry If Necissary
175						if(count($this->subPackets[$this->subPacketNum]) == 0)
176						{
177							$this->subPackets[$this->subPacketNum][0] = '';
178						}
179						$this->subPackets[$this->subPacketNum][3] = $value;
180						$this->subPacketValueNum++;
181						break;
182
183					default:
184						break;
185				}
186				return array($state, $value);
187				break;
188			case DOKU_LEXER_UNMATCHED :
189				break;
190			case DOKU_LEXER_EXIT :
191
192				/********************************************************************************************************************************************
193				** Build Subpacket Details
194				********************************************************************************************************************************************/
195				$details = '';
196				$packetSize = 0;
197
198				//Count Packet Size
199				foreach($this->subPackets as $subPacketVal)
200				{
201					$packetSize += $subPacketVal[1];
202				}
203
204				//Calculate Num Cols
205				$numCols = ($packetSize)*8;
206
207				//Build Packet Breakdown HTML
208				foreach($this->subPackets as $subPacketVal)
209				{
210					$details .= "
211					   <tr>
212						  <td class='subPacketHeaderCell'>
213							 " . $subPacketVal[0] . "
214						  </td>
215						  <td class='subPacketDetailsCell' colspan='32'>
216							 " . $subPacketVal[2] . "
217						  </td>
218					   </tr>";
219				}
220				/************************************************************
221				 * Helper Functions For HTML Generation
222				 *************************************************************/
223
224				//Convert Packet Size From Bits To Bytes
225				$partialByte = 0;
226				if( ($packetSize % 8) > 0)
227				{
228					$partialByte = 1;
229				}
230				$packetNumBytes = (floor($packetSize / 8) + $partialByte);  //Number of full bytes needed to hold the entire packet.
231
232				/********************************************************
233				* Name Row
234				*********************************************************/
235				$nameRow = "<tr>
236								<td class='packetNameCell' colspan='33'>
237									<center>" . $this->name . "</center>
238								</td>
239							</tr>";
240
241				/********************************************************
242				* Description Row
243				*********************************************************/
244				$descriptionRow =  "<tr>
245										<td class='subPacketHeaderCell'>
246											Description
247										</td>
248										<td class='packetDescriptionCell' colspan='32'>
249											" . $this->description . "
250										</td>
251									</tr>";
252				/********************************************************
253				* Size Row
254				*********************************************************/
255				$sizeRow =  "	<tr>
256									<td class='subPacketHeaderCell'>
257										Size
258									</td>
259									<td class='packetSizeCell' colspan='32'>
260										" . $this->size . "
261									</td>
262								</tr>";
263
264				/********************************************************
265				* Format Rows
266				*********************************************************/
267				$numFormatRows = 0;
268				//Calculate Number Of Rows Needed For Format
269				if( ($packetNumBytes % 4) > 0)
270				{
271					$numFormatRows = (floor($packetNumBytes / 4)) + 1;
272				}
273				else
274				{
275					$numFormatRows = floor($packetNumBytes / 4);
276				}
277
278				//Build Each Packet Format Row
279
280				//TODO - Get Rid of This Reverse And Build The Table Top To Bottom.  This Was Implemented This Way Because The Bytes Used To Be Right Justified In The Table But Are Now Top / Left Justified
281				$this->subPackets = array_reverse($this->subPackets);
282
283				$formatRows = "";
284				$partialBitsUsed = 0;
285				$idNum = 0;
286				for($i=0; $i<$numFormatRows; $i++)
287				{
288					//Build It Backwards
289
290					//Build ID Row
291					$idBitsRemaining = 32;
292					$loopCountSafty = 0;
293
294					//Close ID Row
295					$formatRows = "</tr>" . $formatRows;
296
297					//TODO - Add Bits and Bytes and padding at the end (right now we probably read off the end of the array when looking for sub packet sizes ans ids
298
299					//Add Format ID Row
300					while($idBitsRemaining > 0)
301					{
302						//If There Are More IDs To Add Do So
303						if($this->subPackets[$idNum][1] != '')
304						{
305							//Check If There Is Room For The Entire ID On This Format Row
306							$idBitsNeeded = ($this->subPackets[$idNum][1]-$partialBitsUsed);	//Number Of Bit Cols Needed For Next ID Or Partial ID
307
308							if( $idBitsNeeded <= $idBitsRemaining )
309							{
310
311								//Add Entire ID To Current Row
312								$subPacketIDCell = "<td class='packetIdCell' colspan='" . $idBitsNeeded . "'><center>" . $this->subPackets[$idNum][0];
313								//Add Value If Specified
314								if($this->subPackets[$idNum][3] != '')
315								{
316									$subPacketIDCell .= ": " . $this->subPackets[$idNum][3];
317								}
318
319								//Close Sub Packet Cell
320								$subPacketIDCell .= "</center></td>";
321
322								//Add To formatRows
323								$formatRows = $subPacketIDCell . $formatRows;
324
325								$idNum++;
326								$partialBitsUsed = 0;
327								$idBitsRemaining = $idBitsRemaining - $idBitsNeeded;
328							}
329
330							else
331							{
332								//Add Partial ID To Current Row
333								$subPacketIDCell = "<td class='packetIdCell' colspan='" . $idBitsRemaining . "'><center>" . $this->subPackets[$idNum][0];
334								//Add Value If Specified
335								if($this->subPackets[$idNum][3] != '')
336								{
337									$subPacketIDCell .= ": " . $this->subPackets[$idNum][3];
338								}
339
340								//Close Sub Packet Cell
341								$subPacketIDCell .= "</center></td>";
342
343								//Add To formatRows
344								$formatRows = $subPacketIDCell . $formatRows;
345								$partialBitsUsed = $idBitsRemaining;
346								$idBitsRemaining = 0;
347							}
348						}
349						else
350						{
351							//All IDs Have Been Added.  Pad The Rest Of The Row
352							$formatRows = "<td class='packetIdCell' colspan='" . $idBitsRemaining . "'><center>" . "N/A" . "</center></td>" . $formatRows;
353							$idBitsRemaining = 0;
354						}
355
356						//Prevent This Loop From Grinding Forever
357						$loopCountSafty++;
358						if($loopCountSafty > 100)
359						{
360							break;
361						}
362					}
363					//Close Bit Row, Open ID Row
364					$formatRows = "</tr><tr>" . $formatRows;
365
366					//Add Format Bit Row
367					for($j=8; $j<40; $j++)
368					{
369						$formatRows = "<td class='packetBitCell'><center>" . ($j % 8) . "</center></td>" . $formatRows;
370					}
371
372					//Close Byte Row And Open Bits Row
373					$formatRows = "</tr><tr>" . $formatRows;
374
375					//Add Format Byte Row
376					for($j=0; $j<4; $j++)
377					{
378						$byteNum = $packetNumBytes - ( ($i*4) + $j +1 );
379						if($byteNum >= 0)
380						{
381							$formatRows = "<td class='packetByteCell' colspan='8'><center>" . $byteNum . "</center></td>" . $formatRows;
382						}
383						else
384						{
385							$formatRows = "<td class='packetByteCell' colspan='8'><center>-</center></td>" . $formatRows;
386						}
387					}
388				}
389
390				//Prepend Format Row Header
391				$formatRows = "<tr class='packetFormatRow'><td class='subPacketHeaderCell' rowspan='" . ($numFormatRows * 3) . "'>Format</td>" . $formatRows;
392
393				//Build TOC
394
395				//Build Array To Send To Renderer
396				$retVal = array($state, $this->name, $nameRow, $descriptionRow, $sizeRow, $formatRows, $details, $numCols);
397
398				//Clear Variables That Will Be Resused Here If Neccissary
399				$this->name = '';
400				$this->description = '';
401				$this->size = '';
402				$this->format = '';
403				$this->subPackets = '';
404				$this->allPackets = '';
405
406				$this->subPacketNum = 0;
407				$this->subPacketIdNum = 0;
408				$this->subPacketValueNum = 0;
409				$this->subPacketSizeNum = 0;
410				$this->subPacketDetailsNum = 0;
411
412				return $retVal;
413				break;
414			case DOKU_LEXER_SPECIAL :
415				break;
416		}
417		return array($state, $match);
418    }
419
420	/********************************************************************************************************************************************
421	** Render
422	********************************************************************************************************************************************/
423
424    function render($mode, &$renderer, $data)
425	{
426    // $data is what the function handle return'ed.
427        if($mode == 'xhtml')
428		{
429			switch ($data[0])
430			{
431			  case DOKU_LEXER_ENTER :
432				//Initialize Table
433				if($this->lvhDebug) $renderer->doc .= 'ENTER';		//Debug
434
435				//$renderer->doc.= '<HTML><body><table border="0">';
436				break;
437			  case DOKU_LEXER_MATCHED :
438				//Add Table Elements Based On Type
439				if($this->lvhDebug) $renderer->doc .= 'MATCHED';		//Debug
440				break;
441			  case DOKU_LEXER_UNMATCHED :
442				//Ignore
443				if($this->lvhDebug) $renderer->doc .= 'UNMATCHED';	//Debug
444				break;
445			  case DOKU_LEXER_EXIT :
446				//Close Elements
447				if($this->lvhDebug) $renderer->doc .= 'EXIT';		//Debug
448				//$renderer->doc.= '</table></body></HTML>';
449
450				//Separate Data
451				$instPacketName = $data[1];
452				$instNameRow = $data[2];
453				$instDescriptionRow = $data[3];
454				$instSizeRow = $data[4];
455				$instFormatRow = $data[5];
456				$instDetails = $data[6];
457				$instNumCols = $data[7];
458
459
460				/************************************************************
461				* Variables For HTML Generation
462				*************************************************************/
463
464
465				//Add Packet Table
466				$renderer->doc .= "
467					<head>
468							<style type='text/css'>
469
470								table.packetTOC
471								{
472									width:100%;
473									background-color: #FFFFFF;
474									border-style:none;
475									border-spacing:0;
476								}
477
478								td.packetTOCCell
479								{
480									border-style:none;
481								}
482
483								table.packetTable
484								{
485									width:100%;
486									border-style:solid;
487									border-width:2px;
488									border-color:#1C1C1C;
489									border-collapse:collapse;
490									font-size:.9em;
491									background-color: #EEEEEE;
492								}
493
494								tr.packetFormatRow
495								{
496
497								}
498
499								td.packetNameCell
500								{
501									text-align: center;
502									font-size:1.2em;
503									font-weight:bold;
504									background-color: #A4A4A4;
505									border-bottom-style=solid;
506									border-bottom-width:1px;
507									border-bottom-color:#1C1C1C;
508									border-right-style=solid;
509									border-right-width:2px;
510									border-right-color:#1C1C1C;
511
512								}
513								td.packetDescriptionCell
514								{
515
516								}
517
518								td.packetSizeCell
519								{
520									border-bottom-style=solid;
521									border-bottom-width:1px;
522									border-bottom-color:#1C1C1C;
523								}
524
525								td.packetByteCell
526								{
527									text-align: center;
528									background-color: #A4A4A4;
529									font-weight:bold;
530									border-width:1px;
531									border-color:#1C1C1C;
532								}
533
534								td.packetBitCell
535								{
536									text-align: center;
537									background-color: #BBBBBB;
538									font-weight:bold;
539									border-width:1px;
540									border-color:#1C1C1C;
541								}
542								td.packetIdCell
543								{
544									text-align: center;
545									font-weight:bold;
546									background-color: #E6E6E6;
547									border-width:1px;
548									border-color:#1C1C1C;
549								}
550
551								td.subPacketHeaderCell
552								{
553									width:7%;
554									background-color: #A4A4A4;
555									text-align:right;
556									font-weight:bold;
557									border-right-style:solid;
558									border-right-width:1px;
559									border-right-color:#1C1C1C;
560								}
561								td.subPacketDetailsCell
562								{
563
564								}
565							</style>
566					</head>
567
568
569					<body>
570						<table class = packetTOC>
571							<ul>
572								<!--TOC-->
573							</ul>
574						</table>
575						</table>
576
577						<a id='".trim(str_replace(' ', '', $instPacketName))."'></a>
578						<table class='packetTable'>
579							" . $instNameRow
580							  . $instDescriptionRow
581							  . $instSizeRow
582							  . $instFormatRow
583							  . $instDetails . "
584						</table>
585					</body>";
586
587				//Add To Packet TOC
588				$renderer->doc = preg_replace("/<!--TOC-->/", "<tr><td class=packetTOCCell><li><a href='#".trim(str_replace(' ', '', $instPacketName))."'>" . $instPacketName ." </a></li></tr></td><!--TOC-->", $renderer->doc, 1);
589
590				break;
591			  case DOKU_LEXER_SPECIAL :
592				//Ignore
593				if($this->lvhDebug) $renderer->doc .= 'SPECIAL';		//Debug
594				break;
595			}
596            return true;
597        }
598        return false;
599    }
600}
601