1<?php
2/*=========================================================================
3
4  Program:   CDash - Cross-Platform Dashboard System
5  Module:    $Id$
6  Language:  PHP
7  Date:      $Date$
8  Version:   $Revision$
9
10  Copyright (c) 2002 Kitware, Inc.  All rights reserved.
11  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12
13     This software is distributed WITHOUT ANY WARRANTY; without even
14     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15     PURPOSE.  See the above copyright notices for more information.
16
17=========================================================================*/
18require_once("cdash/cdashmail.php");
19
20
21/** Check the email preferences for errors */
22function checkEmailPreferences($emailcategory,$errors,$fixes=false)
23{
24  include_once("cdash/common.php");
25
26  if($fixes)
27    {
28    $updates = 0; // for fixes we don't use update
29    $configures=$errors['fixes']['configure_fixes'];
30    $builderrors=$errors['fixes']['builderror_fixes'];
31    $buildwarnings=$errors['fixes']['buildwarning_fixes'];
32    $tests=$errors['fixes']['test_fixes'];
33    }
34  else
35    {
36    $updates=$errors['update_errors'];
37    $configures=$errors['configure_errors'];
38    $builderrors=$errors['build_errors'];
39    $buildwarnings=$errors['build_warnings'];
40    $tests=$errors['test_errors'];
41    $dynamicanalysis=$errors['dynamicanalysis_errors'];
42    }
43
44  if($configures>0 && check_email_category("configure",$emailcategory))
45    {
46    return true;
47    }
48  if($buildwarnings>0 && check_email_category("warning",$emailcategory))
49    {
50    return true;
51    }
52  if($builderrors>0 && check_email_category("error",$emailcategory))
53    {
54    return true;
55    }
56  if($tests>0 && check_email_category("test",$emailcategory))
57    {
58    return true;
59    }
60  if($dynamicanalysis>0 && check_email_category("dynamicanalysis",$emailcategory))
61    {
62    return true;
63    }
64  return false;
65}
66
67/** Given a user check if we should send an email based on labels */
68function checkEmailLabel($projectid, $userid, $buildid, $emailcategory=62)
69{
70  include_once("models/labelemail.php");
71  include_once("models/build.php");
72  $LabelEmail = new LabelEmail();
73  $LabelEmail->UserId = $userid;
74  $LabelEmail->ProjectId = $projectid;
75
76  $labels = $LabelEmail->GetLabels();
77  if(count($labels)==0) // if the number of subscribed labels is zero we send the email
78    {
79    return true;
80    }
81
82  $Build = new Build();
83  $Build->Id = $buildid;
84
85  $labelarray = array();
86
87  if(check_email_category("update",$emailcategory))
88    {
89    $labelarray['update']['errors']=1;
90    }
91  if(check_email_category("configure",$emailcategory))
92    {
93    $labelarray['configure']['errors']=1;
94    }
95  if(check_email_category("warning",$emailcategory))
96    {
97    $labelarray['build']['warnings']=1;
98    }
99  if(check_email_category("error",$emailcategory))
100    {
101    $labelarray['build']['errors']=1;
102    }
103  if(check_email_category("test",$emailcategory))
104    {
105    $labelarray['test']['errors']=1;
106    }
107
108  $buildlabels = $Build->GetLabels($labelarray);
109  if(count(array_intersect($labels, $buildlabels))>0)
110    {
111    return true;
112    }
113  return false;
114} // end checkEmailLabel
115
116/** Check for errors for a given build. Return false if no errors */
117function check_email_errors($buildid,$checktesttimeingchanged,$testtimemaxstatus,$checkpreviouserrors)
118{
119  // Includes
120  require_once("models/buildupdate.php");
121  require_once("models/buildconfigure.php");
122  require_once("models/build.php");
123  require_once("models/buildtest.php");
124  require_once("models/dynamicanalysis.php");
125
126  $errors = array();
127  $errors['errors'] = true;
128  $errors['hasfixes'] = false;
129
130  // Update errors
131  $BuildUpdate = new BuildUpdate();
132  $BuildUpdate->BuildId = $buildid;
133  $errors['update_errors'] = $BuildUpdate->GetNumberOfErrors();
134
135  // Configure errors
136  $BuildConfigure = new BuildConfigure();
137  $BuildConfigure->BuildId = $buildid;
138  $errors['configure_errors'] = $BuildConfigure->GetNumberOfErrors();
139
140  // Build errors and warnings
141  $Build = new Build();
142  $Build->Id = $buildid;
143  $Build->FillFromId($buildid);
144  $errors['build_errors'] = $Build->GetNumberOfErrors();
145  $errors['build_warnings'] = $Build->GetNumberOfWarnings();
146
147  // Test errors
148  $BuildTest = new BuildTest();
149  $BuildTest->BuildId = $buildid;
150  $errors['test_errors'] = $BuildTest->GetNumberOfFailures($checktesttimeingchanged,$testtimemaxstatus);
151
152  // Dynamic analysis errors
153  $DynamicAnalysis = new DynamicAnalysis();
154  $DynamicAnalysis->BuildId = $buildid;
155  $errors['dynamicanalysis_errors'] = $DynamicAnalysis->GetNumberOfErrors();
156
157  // Green build we return
158  if( $errors['update_errors'] == 0
159     && $errors['configure_errors'] == 0
160     && $errors['build_errors'] == 0
161     && $errors['build_warnings'] ==0
162     && $errors['test_errors'] ==0
163     && $errors['dynamicanalysis_errors'] == 0)
164    {
165    $errors['errors'] = false;
166    }
167
168
169  // look for the previous build
170  $previousbuildid = $Build->GetPreviousBuildId();
171  if($previousbuildid > 0)
172    {
173    $error_differences = $Build->GetErrorDifferences($buildid);
174    if($errors['errors'] && $checkpreviouserrors && $errors['dynamicanalysis_errors'] == 0)
175      {
176      // If the builderroddiff positive and configureerrordiff and testdiff positive are zero we don't send an email
177      // we don't send any emails
178      if($error_differences['buildwarningspositive']<=0
179         && $error_differences['builderrorspositive']<=0
180         && $error_differences['configurewarnings']<=0
181         && $error_differences['configureerrors']<=0
182         && $error_differences['testfailedpositive']<=0
183         && $error_differences['testnotrunpositive']<=0
184        )
185        {
186        $errors['errors'] = false;
187        }
188      } // end checking previous errors
189
190    if($error_differences['buildwarningsnegative']>0
191       || $error_differences['builderrorsnegative']>0
192       || $error_differences['configurewarnings']<0
193       || $error_differences['configureerrors']<0
194       || $error_differences['testfailednegative']>0
195       || $error_differences['testnotrunnegative']>0
196       )
197      {
198      $errors['hasfixes'] = true;
199      $errors['fixes']['configure_fixes'] = $error_differences['configurewarnings']+$error_differences['configureerrors'];
200      $errors['fixes']['builderror_fixes'] =  $error_differences['builderrorsnegative'];
201      $errors['fixes']['buildwarning_fixes'] = $error_differences['buildwarningsnegative'];
202      $errors['fixes']['test_fixes'] = $error_differences['testfailednegative']+$error_differences['testnotrunnegative'];
203      }
204    } // end has previous build
205
206  return $errors;
207}
208
209/** Check for update errors for a given build. */
210function check_email_update_errors($buildid)
211{
212  // Includes
213  require_once("models/buildupdate.php");
214  require_once("models/build.php");
215
216  $errors = array();
217  $errors['errors'] = true;
218  $errors['hasfixes'] = false;
219
220  // Update errors
221  $BuildUpdate = new BuildUpdate();
222  $BuildUpdate->BuildId = $buildid;
223  $errors['update_errors'] = $BuildUpdate->GetNumberOfErrors();
224
225  // Green build we return
226  if( $errors['update_errors'] == 0 )
227    {
228    $errors['errors'] = false;
229    }
230
231  return $errors;
232}
233
234
235/** Return the list of user id and committer emails who should get emails */
236function lookup_emails_to_send($errors, $buildid, $projectid, $buildtype, $fixes=false, $collectUnregisteredCommitters=false)
237{
238  require_once("models/userproject.php");
239
240  $userids = array();
241  $committeremails = array();
242
243  // Check if we know to whom we should send the email
244  $updatefiles = pdo_query("SELECT author,email,committeremail FROM updatefile AS uf,build2update AS b2u
245                            WHERE b2u.updateid=uf.updateid AND b2u.buildid=".qnum($buildid));
246  add_last_sql_error("sendmail",$projectid,$buildid);
247  while($updatefiles_array = pdo_fetch_array($updatefiles))
248    {
249    $author = $updatefiles_array["author"];
250
251    // Skip the Local User, old CVS/SVN issue
252    if($author=="Local User")
253      {
254      continue;
255      }
256
257    $emails = array();
258    $authorEmail = $updatefiles_array["email"];
259    $emails[] = $authorEmail;
260    $committerEmail = $updatefiles_array["committeremail"];
261    if($committerEmail != '' && $committerEmail != $authorEmail)
262      {
263      $emails[] = $committerEmail;
264      }
265
266    foreach($emails as $email)
267      {
268      $UserProject = new UserProject();
269      $UserProject->RepositoryCredential = $author;
270      $UserProject->ProjectId = $projectid;
271
272      $filled = false;
273      if($email != '')
274        {
275        $result = pdo_query("SELECT id FROM ".qid("user")." WHERE email='$email'");
276
277        if(pdo_num_rows($result) != 0)
278          {
279          $user_array = pdo_fetch_array($result);
280          $id = $user_array['id'];
281          $UserProject->UserId = $id;
282          $filled = $UserProject->FillFromUserId();
283          }
284        }
285
286      if(!$filled && !$UserProject->FillFromRepositoryCredential())
287        {
288        global $CDASH_WARN_ABOUT_UNREGISTERED_COMMITTERS;
289        global $CDASH_TESTING_MODE;
290        if (!$CDASH_TESTING_MODE && $CDASH_WARN_ABOUT_UNREGISTERED_COMMITTERS)
291          {
292          $name = $email == '' ? $author : $email;
293          // Daily updates send an email to tell adminsitrator that the user
294          // is not registered but we log anyway
295          add_log("User: ".$name." is not registered (or has no email) for the project ".$projectid,
296            "SendEmail", LOG_WARNING, $projectid, $buildid);
297          }
298        if ($collectUnregisteredCommitters && $email != '' &&
299            !in_array($email, $committeremails))
300          {
301          $committeremails[] = $email;
302          }
303        continue;
304        }
305
306      // If we already have this user in the array, don't bother checking
307      // user preferences again... (avoid below calls to checkEmail*
308      // functions)
309      if(in_array($UserProject->UserId, $userids))
310        {
311        continue;
312        }
313
314      // If the user doesn't want to receive email
315      if($fixes && !$UserProject->EmailSuccess)
316        {
317        continue;
318        }
319
320      // Check the categories
321      if(!checkEmailPreferences($UserProject->EmailCategory,$errors,$fixes))
322        {
323        continue;
324        }
325
326      // Check if the labels are defined for this user
327      if(!checkEmailLabel($projectid,$UserProject->UserId, $buildid, $UserProject->EmailCategory))
328        {
329        continue;
330        }
331
332      $userids[] = $UserProject->UserId;
333      }
334    }
335
336  // If it's fixes only concerned users should get the email
337  if($fixes)
338    {
339    $result = array();
340    $result['userids'] = $userids;
341    $result['committeremails'] = $committeremails;
342    return $result;
343    }
344
345  // Select the users who want to receive all emails
346  $user = pdo_query("SELECT emailtype,emailcategory,userid FROM user2project WHERE user2project.projectid=".qnum($projectid)." AND user2project.emailtype>1");
347  add_last_sql_error("sendmail");
348  while($user_array = pdo_fetch_array($user))
349    {
350    if(in_array($user_array["userid"],$userids))
351      {
352      continue;
353      }
354
355    // If the user doesn't want to receive email
356    if(!checkEmailPreferences($user_array["emailcategory"],$errors))
357      {
358      continue;
359      }
360
361    // Check if the labels are defined for this user
362    if(!checkEmailLabel($projectid,$user_array['userid'],$buildid, $user_array["emailcategory"]))
363      {
364      continue;
365      }
366
367    // Nightly build notification
368    if($user_array["emailtype"] == 2 && $buildtype=="Nightly")
369      {
370      $userids[] = $user_array["userid"];
371      }
372    else if($user_array["emailtype"] == 3) // want to receive all emails
373      {
374      $userids[] = $user_array["userid"];
375      }
376    }
377
378  $result = array();
379  $result['userids'] = $userids;
380  $result['committeremails'] = $committeremails;
381  return $result;
382
383} // end lookup_emails_to_send
384
385
386/** Return a summary for a category of error */
387function get_email_summary($buildid,$errors,$errorkey,$maxitems,$maxchars,$testtimemaxstatus,$emailtesttimingchanged)
388{
389  include("cdash/config.php");
390
391  $serverURI = get_server_URI();
392  // In the case of asynchronous submission, the serverURI contains /cdash
393  // we need to remove it
394  if($CDASH_BASE_URL=='' && $CDASH_ASYNCHRONOUS_SUBMISSION)
395    {
396    $serverURI = substr($serverURI,0,strrpos($serverURI,"/"));
397    }
398
399  $information = "";
400
401  // Update information
402  if($errorkey == 'update_errors')
403    {
404    $information = "\n\n*Update*\n";
405
406    $update = pdo_query("SELECT command,status FROM buildupdate AS u,build2update AS b2u
407                            WHERE b2u.updateid=u.id AND b2u.buildid=".qnum($buildid));
408    $update_array = pdo_fetch_array($update);
409
410    $information .= "Status: ".$update_array["status"]." (".$serverURI."/viewUpdate.php?buildid=".$buildid.")\n";
411    $information .= "Command: ";
412    $information .= substr($update_array["command"],0,$maxchars);
413    $information .= "\n";
414    } // endconfigure
415  else if($errorkey == 'configure_errors') // Configure information
416    {
417    $information = "\n\n*Configure*\n";
418
419    $configure = pdo_query("SELECT status,log FROM configure WHERE buildid=".qnum($buildid));
420    $configure_array = pdo_fetch_array($configure);
421
422    $information .= "Status: ".$configure_array["status"]." (".$serverURI."/viewConfigure.php?buildid=".$buildid.")\n";
423    $information .= "Output: ";
424    $information .= substr($configure_array["log"],0,$maxchars);
425    $information .= "\n";
426    } // endconfigure
427  else if($errorkey == 'build_errors')
428    {
429    $information .= "\n\n*Error*";
430
431    // Old error format
432    $error_query = pdo_query("SELECT sourcefile,text,sourceline,postcontext FROM builderror WHERE buildid=".qnum($buildid)." AND type=0 LIMIT $maxitems");
433    add_last_sql_error("sendmail");
434
435    if(pdo_num_rows($error_query) == $maxitems)
436      {
437      $information .= " (first ".$maxitems.")";
438      }
439    $information .= "\n";
440
441    while($error_array = pdo_fetch_array($error_query))
442      {
443      $info = "";
444      if(strlen($error_array["sourcefile"])>0)
445        {
446        $info .= $error_array["sourcefile"]." line ".$error_array["sourceline"]." (".$serverURI."/viewBuildError.php?type=0&buildid=".$buildid.")\n";
447        $info .= $error_array["text"]."\n";
448        }
449      else
450        {
451        $info .= $error_array["text"]."\n".$error_array["postcontext"]."\n";
452        }
453      $information .= substr($info,0,$maxchars);
454      }
455
456    // New error format
457    $error_query = pdo_query("SELECT sourcefile,stdoutput,stderror FROM buildfailure WHERE buildid=".qnum($buildid)." AND type=0 LIMIT $maxitems");
458    add_last_sql_error("sendmail");
459    while($error_array = pdo_fetch_array($error_query))
460      {
461      $info = "";
462      if(strlen($error_array["sourcefile"])>0)
463        {
464        $info .= $error_array["sourcefile"]." (".$serverURI."/viewBuildError.php?type=0&buildid=".$buildid.")\n";
465        }
466      if(strlen($error_array["stdoutput"])>0)
467        {
468        $info .= $error_array["stdoutput"]."\n";
469        }
470      if(strlen($error_array["stderror"])>0)
471        {
472        $info .= $error_array["stderror"]."\n";
473        }
474      $information .= substr($info,0,$maxchars);
475      }
476    $information .= "\n";
477    }
478  else if($errorkey == 'build_warnings')
479    {
480    $information .= "\n\n*Warnings*";
481
482    $error_query = pdo_query("SELECT sourcefile,text,sourceline,postcontext FROM builderror
483                              WHERE buildid=".qnum($buildid)." AND type=1 ORDER BY logline LIMIT $maxitems");
484    add_last_sql_error("sendmail");
485
486    if(pdo_num_rows($error_query) == $maxitems)
487      {
488      $information .= " (first ".$maxitems.")";
489      }
490    $information .= "\n";
491
492    while($error_array = pdo_fetch_array($error_query))
493      {
494      $info = "";
495      if(strlen($error_array["sourcefile"])>0)
496        {
497        $info .= $error_array["sourcefile"]." line ".$error_array["sourceline"]." (".$serverURI."/viewBuildError.php?type=1&buildid=".$buildid.")\n";
498        $info .= $error_array["text"]."\n";
499        }
500      else
501        {
502        $info .= $error_array["text"]."\n".$error_array["postcontext"]."\n";
503        }
504      $information .= substr($info,0,$maxchars);
505      }
506
507    // New error format
508    $error_query = pdo_query("SELECT sourcefile,stdoutput,stderror FROM buildfailure WHERE buildid=".qnum($buildid).
509                             " AND type=1 ORDER BY id LIMIT $maxitems");
510    add_last_sql_error("sendmail");
511    while($error_array = pdo_fetch_array($error_query))
512      {
513      $info = "";
514      if(strlen($error_array["sourcefile"])>0)
515        {
516        $info .= $error_array["sourcefile"]." (".$serverURI."/viewBuildError.php?type=1&buildid=".$buildid.")\n";
517        }
518      if(strlen($error_array["stdoutput"])>0)
519        {
520        $info .= $error_array["stdoutput"]."\n";
521        }
522      if(strlen($error_array["stderror"])>0)
523        {
524        $info .= $error_array["stderror"]."\n";
525        }
526      $information .= substr($info,0,$maxchars)."\n";
527      }
528    $information .= "\n";
529    }
530 else if($errorkey == 'test_errors')
531    {
532    $sql = "";
533    if($emailtesttimingchanged)
534      {
535      $sql = "OR timestatus>".qnum($testtimemaxstatus);
536      }
537    $test_query = pdo_query("SELECT test.name,test.id FROM build2test,test WHERE build2test.buildid=".qnum($buildid).
538                            " AND test.id=build2test.testid AND (build2test.status='failed'".$sql.") ORDER BY test.id LIMIT $maxitems");
539    add_last_sql_error("sendmail");
540    $numrows = pdo_num_rows($test_query);
541
542    if($numrows>0)
543      {
544      $information .= "\n\n*Tests failing*";
545      if(pdo_num_rows($test_query) == $maxitems)
546        {
547        $information .= " (first ".$maxitems.")";
548        }
549      $information .= "\n";
550
551      while($test_array = pdo_fetch_array($test_query))
552        {
553        $info = $test_array["name"]." (".$serverURI."/testDetails.php?test=".$test_array["id"]."&build=".$buildid.")\n";
554        $information .= substr($info,0,$maxchars);
555        }
556      $information .= "\n";
557      } // end test failing > 0
558
559    // Add the tests not run
560    $test_query = pdo_query("SELECT test.name,test.id FROM build2test,test WHERE build2test.buildid=".qnum($buildid).
561                            " AND test.id=build2test.testid AND (build2test.status='notrun'".$sql.") ORDER BY test.id LIMIT $maxitems");
562    add_last_sql_error("sendmail");
563    $numrows = pdo_num_rows($test_query);
564
565    if($numrows>0)
566      {
567      $information .= "\n\n*Tests not run*";
568      if(pdo_num_rows($test_query) == $maxitems)
569        {
570        $information .= " (first ".$maxitems.")";
571        }
572      $information .= "\n";
573
574      while($test_array = pdo_fetch_array($test_query))
575        {
576        $info = $test_array["name"]." (".$serverURI."/testDetails.php?test=".$test_array["id"]."&build=".$buildid.")\n";
577        $information .= substr($info,0,$maxchars);
578        }
579      $information .= "\n";
580      } // end test not run > 0
581    }
582  else if($errorkey == "dynamicanalysis_errors")
583    {
584    $da_query = pdo_query("SELECT name,id FROM dynamicanalysis WHERE status IN ('failed','notrun') AND buildid="
585        .qnum($buildid)." ORDER BY name LIMIT $maxitems");
586    add_last_sql_error("sendmail");
587    $numrows = pdo_num_rows($da_query);
588
589    if($numrows>0)
590      {
591      $information .= "\n\n*Dynamic analysis tests failing or not run*";
592      if($numrows == $maxitems)
593        {
594        $information .= " (first ".$maxitems.")";
595        }
596      $information .= "\n";
597
598      while($test_array = pdo_fetch_array($da_query))
599        {
600        $info = $test_array["name"]." (".$serverURI."/viewDynamicAnalysisFile.php?id=".$test_array["id"].")\n";
601        $information .= substr($info,0,$maxchars);
602        }
603      $information .= "\n";
604      } // end test failing > 0
605    }
606
607  return $information;
608} // end get_email_summary
609
610
611/** Send a summary email */
612function sendsummaryemail($projectid,$groupid,$errors,$buildid)
613{
614  include("cdash/config.php");
615  require_once("models/userproject.php");
616  require_once("models/user.php");
617  require_once("models/project.php");
618
619  $Project = new Project();
620  $Project->Id = $projectid;
621  $Project->Fill();
622
623  // Check if the email has been sent
624  $date = ""; // now
625  list ($previousdate, $currentstarttime, $nextdate, $today) = get_dates($date,$Project->NightlyTime);
626  $dashboarddate = gmdate(FMT_DATE, $currentstarttime);
627
628  // If we already have it we return
629  if(pdo_num_rows(pdo_query("SELECT buildid FROM summaryemail WHERE date='$dashboarddate' AND groupid=".qnum($groupid)))==1)
630    {
631    return;
632    }
633
634  // Update the summaryemail table to specify that we have send the email
635  // We also delete any previous rows from that groupid
636  pdo_query("DELETE FROM summaryemail WHERE groupid=$groupid");
637  pdo_query("INSERT INTO summaryemail (buildid,date,groupid) VALUES ($buildid,'$dashboarddate',$groupid)");
638  add_last_sql_error("sendmail");
639
640  // If the trigger for SVN/CVS diff is not done yet we specify that the asynchronous trigger should
641  // send an email
642  $dailyupdatequery = pdo_query("SELECT status FROM dailyupdate WHERE projectid=".qnum($projectid)." AND date='$dashboarddate'");
643  add_last_sql_error("sendmail");
644
645  if(pdo_num_rows($dailyupdatequery) == 0)
646    {
647    return;
648    }
649
650  $dailyupdate_array = pdo_fetch_array($dailyupdatequery);
651  $dailyupdate_status = $dailyupdate_array['status'];
652  if($dailyupdate_status == 0)
653    {
654    pdo_query("UPDATE dailyupdate SET status='2' WHERE projectid=".qnum($projectid)." AND date='$dashboarddate'");
655    return;
656    }
657
658  // Find the current updaters from the night using the dailyupdatefile table
659  $summaryEmail = "";
660  $query = "SELECT ".qid("user").".email,up.emailcategory,".qid("user").".id
661                          FROM ".qid("user").",user2project AS up,user2repository AS ur,
662                           dailyupdate,dailyupdatefile WHERE
663                           up.projectid=".qnum($projectid)."
664                           AND up.userid=".qid("user").".id
665                           AND ur.userid=up.userid
666                           AND (ur.projectid=0 OR ur.projectid=".qnum($projectid).")
667                           AND ur.credential=dailyupdatefile.author
668                           AND dailyupdatefile.dailyupdateid=dailyupdate.id
669                           AND dailyupdate.date='$dashboarddate'
670                           AND dailyupdate.projectid=".qnum($projectid)."
671                           AND up.emailtype>0
672                           ";
673  $user = pdo_query($query);
674  add_last_sql_error("sendmail");
675
676  // Loop through the users and add them to the email array
677  while($user_array = pdo_fetch_array($user))
678    {
679    // If the user is already in the list we quit
680    if(strpos($summaryEmail,$user_array["email"]) !== false)
681      {
682      continue;
683      }
684
685    // If the user doesn't want to receive email
686    if(!checkEmailPreferences($user_array["emailcategory"],$errors))
687      {
688      continue;
689      }
690
691    // Check if the labels are defined for this user
692    if(!checkEmailLabel($projectid, $user_array["id"], $buildid, $user_array["emailcategory"]))
693      {
694      continue;
695      }
696
697    if($summaryEmail != "")
698      {
699      $summaryEmail .= ", ";
700      }
701    $summaryEmail .= $user_array["email"];
702    }
703
704  // Select the users that are part of this build
705  $authors = pdo_query("SELECT author FROM updatefile AS uf,build2update AS b2u
706                        WHERE b2u.updateid=uf.updateid AND b2u.buildid=".qnum($buildid));
707  add_last_sql_error("sendmail");
708  while($authors_array = pdo_fetch_array($authors))
709    {
710    $author = $authors_array["author"];
711    if($author=="Local User")
712      {
713      continue;
714      }
715
716    $UserProject = new UserProject();
717    $UserProject->RepositoryCredential = $author;
718    $UserProject->ProjectId = $projectid;
719
720    if(!$UserProject->FillFromRepositoryCredential())
721      {
722      continue;
723      }
724
725    // If the user doesn't want to receive email
726    if(!checkEmailPreferences($UserProject->EmailCategory,$errors))
727      {
728      continue;
729      }
730
731    // Check if the labels are defined for this user
732    if(!checkEmailLabel($projectid,$UserProject->UserId, $buildid, $UserProject->EmailCategory))
733      {
734      continue;
735      }
736
737    // Find the email
738    $User = new User();
739    $User->Id = $UserProject->UserId;
740    $useremail = $User->GetEmail();
741
742    // If the user is already in the list we quit
743    if(strpos($summaryEmail,$useremail) !== false)
744       {
745       continue;
746       }
747
748    if($summaryEmail != "")
749      {
750      $summaryEmail .= ", ";
751      }
752    $summaryEmail .= $useremail;
753    }
754
755  // In the case of asynchronous submission, the serverURI contains /cdash
756  // we need to remove it
757  $currentURI = get_server_URI();
758  if($CDASH_BASE_URL=='' && $CDASH_ASYNCHRONOUS_SUBMISSION)
759    {
760    $currentURI = substr($currentURI,0,strrpos($currentURI,"/"));
761    }
762
763  // Select the users who want to receive all emails
764  $user = pdo_query("SELECT ".qid("user").".email,user2project.emailtype,".qid("user").".id  FROM ".qid("user").",user2project
765                     WHERE user2project.projectid=".qnum($projectid)."
766                     AND user2project.userid=".qid("user").".id AND user2project.emailtype>1");
767  add_last_sql_error("sendsummaryemail");
768  while($user_array = pdo_fetch_array($user))
769    {
770    // If the user is already in the list we quit
771    if(strpos($summaryEmail,$user_array["email"]) !== false)
772       {
773       continue;
774       }
775
776    // Check if the labels are defined for this user
777    if(!checkEmailLabel($projectid, $user_array["id"], $buildid))
778      {
779      continue;
780      }
781
782    if($summaryEmail != "")
783      {
784      $summaryEmail .= ", ";
785      }
786    $summaryEmail .= $user_array["email"];
787    }
788
789  // Send the email
790  if($summaryEmail != "")
791    {
792    $summaryemail_array = pdo_fetch_array(pdo_query("SELECT name FROM buildgroup WHERE id=$groupid"));
793    add_last_sql_error("sendsummaryemail");
794
795    $title = "CDash [".$Project->Name."] - ".$summaryemail_array["name"]." Failures";
796
797    $messagePlainText = "The \"".$summaryemail_array["name"]."\" group has either errors, warnings or test failures.\n";
798    $messagePlainText .= "You have been identified as one of the authors who have checked in changes that are part of this submission ";
799    $messagePlainText .= "or you are listed in the default contact list.\n\n";
800
801    $messagePlainText .= "To see this dashboard:\n";
802    $messagePlainText .= $currentURI;
803    $messagePlainText .= "/index.php?project=".urlencode($Project->Name)."&date=".$today;
804    $messagePlainText .= "\n\n";
805
806    $messagePlainText .= "Summary of the first build failure:\n";
807    // Check if an email has been sent already for this user
808    foreach($errors as $errorkey => $nerrors)
809      {
810       $messagePlainText .= get_email_summary($buildid,$errors,$errorkey,$Project->EmailMaxItems,
811                                             $Project->EmailMaxChars,$Project->TestTimeMaxStatus,
812                                             $Project->EmailTestTimingChanged);
813      }
814    $messagePlainText .= "\n\n";
815
816    $serverName = $CDASH_SERVER_NAME;
817    if(strlen($serverName) == 0)
818      {
819      $serverName = $_SERVER['SERVER_NAME'];
820      }
821
822    $messagePlainText .= "\n-CDash on ".$serverName."\n";
823
824    // If this is the testing
825    if($CDASH_TESTING_MODE)
826      {
827      add_log($summaryEmail,"TESTING: EMAIL",LOG_TESTING);
828      add_log($title,"TESTING: EMAILTITLE",LOG_TESTING);
829      add_log($messagePlainText,"TESTING: EMAILBODY",LOG_TESTING);
830      }
831    else
832      {
833      // Send the email
834      if(cdashmail("$summaryEmail", $title, $messagePlainText,
835           "From: CDash <".$CDASH_EMAIL_FROM.">\nReply-To: ".$CDASH_EMAIL_REPLY."\nContent-type: text/plain; charset=utf-8\nX-Mailer: PHP/" . phpversion()."\nMIME-Version: 1.0" ))
836        {
837        add_log("summary email sent to: ".$summaryEmail,"sendemail ".$Project->Name,LOG_INFO);
838        return;
839        }
840      else
841        {
842        add_log("cannot send summary email to: ".$summaryEmail,"sendemail ".$Project->Name,LOG_ERR);
843        }
844      }
845    } // end $summaryEmail!=""
846}
847
848/** Check if the email has already been sent for that category */
849function set_email_sent($userid,$buildid,$emailtext)
850{
851  foreach($emailtext['category'] as $key=>$value)
852    {
853    $category = 0;
854    switch($key)
855      {
856      case 'update_errors': $category=1; break;
857      case 'configure_errors': $category=2; break;
858      case 'build_warnings': $category=3; break;
859      case 'build_errors': $category=4; break;
860      case 'test_errors': $category=5; break;
861      case 'update_fixes': $category=6; break;
862      case 'configure_fixes': $category=7; break;
863      case 'buildwarning_fixes': $category=8; break;
864      case 'builderror_fixes': $category=9; break;
865      case 'test_fixes': $category=10; break;
866      case 'dynamicanalysis_errors': $category=11; break;
867      }
868
869   if($category>0)
870     {
871     $today = date(FMT_DATETIME);
872     pdo_query("INSERT INTO buildemail (userid,buildid,category,time) VALUES (".qnum($userid).",".qnum($buildid).",".qnum($category).",'".$today."')");
873     add_last_sql_error("sendmail");
874     }
875   }
876}
877
878/** Check if the email has already been sent for that category */
879function check_email_sent($userid,$buildid,$errorkey)
880{
881  if($userid == 0)
882    {
883    return false;
884    }
885
886  $category = 0;
887  switch($errorkey)
888    {
889    case 'update_errors': $category=1; break;
890    case 'configure_errors': $category=2; break;
891    case 'build_warnings': $category=3; break;
892    case 'build_errors': $category=4; break;
893    case 'test_errors': $category=5; break;
894    case 'update_fixes': $category=6; break;
895    case 'configure_fixes': $category=7; break;
896    case 'buildwarning_fixes': $category=8; break;
897    case 'builderror_fixes': $category=9; break;
898    case 'test_fixes': $category=10; break;
899    case 'dynamicanalysis_errors': $category=11; break;
900    }
901
902  if($category == 0)
903    {
904    return false;
905    }
906
907  $query = pdo_query("SELECT count(*) FROM buildemail WHERE userid=".qnum($userid)." AND buildid=".qnum($buildid)." AND category=".qnum($category));
908  $query_array = pdo_fetch_array($query);
909  if($query_array[0]>0)
910    {
911    return true;
912    }
913
914  return false;
915}
916
917/** Send the email to the user when he fixed something */
918function send_email_fix_to_user($userid,$emailtext,$Build,$Project)
919{
920  include("cdash/config.php");
921  include_once("cdash/common.php");
922  require_once("models/site.php");
923  require_once("models/user.php");
924
925  $serverURI = get_server_URI();
926  // In the case of asynchronous submission, the serverURI contains /cdash
927  // we need to remove it
928  if($CDASH_BASE_URL=='' && $CDASH_ASYNCHRONOUS_SUBMISSION)
929    {
930    $serverURI = substr($serverURI,0,strrpos($serverURI,"/"));
931    }
932
933  $messagePlainText = "Congratulations, a submission to CDash for the project ".$Project->Name." has ";
934  $titleerrors = "(";
935
936  $i=0;
937  foreach($emailtext['category'] as $key=>$value)
938    {
939    if($i>0)
940       {
941       $messagePlainText .= " and ";
942       $titleerrors.=", ";
943       }
944
945    switch($key)
946      {
947      case 'update_fixes': $messagePlainText .= "fixed update errors";$titleerrors.="u=".$value; break;
948      case 'configure_fixes': $messagePlainText .= "fixed configure errors";$titleerrors.="c=".$value; break;
949      case 'buildwarning_fixes': $messagePlainText .= "fixed build warnings";$titleerrors.="w=".$value; break;
950      case 'builderror_fixes': $messagePlainText .= "fixed build errors";$titleerrors.="b=".$value; break;
951      case 'test_fixes': $messagePlainText .= "fixed failing tests";$titleerrors.="t=".$value; break;
952      }
953
954    $i++;
955    }
956
957  // Title
958  $titleerrors .= "):";
959  $title = "PASSED ".$titleerrors." ".$Project->Name;
960
961  if($Build->GetSubProjectName())
962    {
963    $title .= "/".$Build->GetSubProjectName();
964    }
965  $title .= " - ".$Build->Name." - ".$Build->Type;
966
967  $messagePlainText .= ".\n";
968  $messagePlainText .= "You have been identified as one of the authors who have checked in changes that are part of this submission ";
969  $messagePlainText .= "or you are listed in the default contact list.\n\n";
970  $messagePlainText .= "Details on the submission can be found at ";
971
972  $messagePlainText .= $serverURI;
973  $messagePlainText .= "/buildSummary.php?buildid=".$Build->Id;
974  $messagePlainText .= "\n\n";
975
976  $messagePlainText .= "Project: ".$Project->Name."\n";
977  if($Build->GetSubProjectName())
978    {
979    $messagePlainText .= "SubProject: ".$Build->GetSubProjectName()."\n";
980    }
981
982  $Site  = new Site();
983  $Site->Id = $Build->SiteId;
984
985  $messagePlainText .= "Site: ".$Site->GetName()."\n";
986  $messagePlainText .= "Build Name: ".$Build->Name."\n";
987  $messagePlainText .= "Build Time: ".date(FMT_DATETIMETZ,strtotime($Build->StartTime." UTC"))."\n";
988  $messagePlainText .= "Type: ".$Build->Type."\n";
989
990  foreach($emailtext['category'] as $key=>$value)
991    {
992    switch($key)
993      {
994      case 'update_fixes': $messagePlainText .= "Update error fixed: ".$value."\n"; break;
995      case 'configure_fixes': $messagePlainText .= "Configure error fixed: ".$value."\n"; break;
996      case 'buildwarning_fixes': $messagePlainText .= "Warning fixed: ".$value."\n"; break;
997      case 'builderror_fixes': $messagePlainText .= "Error fixed: ".$value."\n"; break;
998      case 'test_fixes': $messagePlainText .= "Tests fixed: ".$value."\n"; break;
999      }
1000    }
1001
1002  $serverName = $CDASH_SERVER_NAME;
1003  if(strlen($serverName) == 0)
1004    {
1005    $serverName = $_SERVER['SERVER_NAME'];
1006    }
1007  $messagePlainText .= "\n-CDash on ".$serverName."\n";
1008
1009  // Find the email
1010  $User = new User();
1011  $User->Id = $userid;
1012  $email = $User->GetEmail();
1013
1014  // If this is the testing
1015  if($CDASH_TESTING_MODE)
1016    {
1017    add_log($email,"TESTING: EMAIL",LOG_TESTING);
1018    add_log($title,"TESTING: EMAILTITLE",LOG_TESTING);
1019    add_log($messagePlainText,"TESTING: EMAILBODY",LOG_TESTING);
1020    // Record that we have send the email
1021    set_email_sent($userid,$Build->Id,$emailtext);
1022    }
1023  else
1024    {
1025    // Send the email
1026    if(cdashmail("$email", $title, $messagePlainText,
1027     "From: CDash <".$CDASH_EMAIL_FROM.">\nReply-To: ".$CDASH_EMAIL_REPLY."\nContent-type: text/plain; charset=utf-8\nX-Mailer: PHP/" . phpversion()."\nMIME-Version: 1.0" ))
1028      {
1029      add_log("email sent to: ".$email." with fixes ".$titleerrors." for build ".$Build->Id,"sendemail ".$Project->Name,LOG_INFO);
1030
1031      // Record that we have send the email
1032      set_email_sent($userid,$Build->Id,$emailtext);
1033      }
1034    else
1035      {
1036      add_log("cannot send email to: ".$email,"sendemail ".$Project->Name,LOG_ERR);
1037      }
1038    } // end if testing
1039} // end send_email_fix_to_user
1040
1041
1042// Send one broken submission email to one email address
1043//
1044function send_email_to_address($emailaddress, $emailtext, $Build, $Project)
1045{
1046  include("cdash/config.php");
1047  include_once("cdash/common.php");
1048  require_once("models/site.php");
1049
1050  $serverURI = get_server_URI();
1051  // In the case of asynchronous submission, the serverURI contains /cdash
1052  // we need to remove it
1053  if($CDASH_BASE_URL=='' && $CDASH_ASYNCHRONOUS_SUBMISSION)
1054    {
1055    $serverURI = substr($serverURI,0,strrpos($serverURI,"/"));
1056    }
1057
1058  $messagePlainText = "A submission to CDash for the project ".$Project->Name." has ";
1059  $titleerrors = "(";
1060
1061  $i=0;
1062  foreach($emailtext['category'] as $key=>$value)
1063    {
1064    if($key != 'update_errors'
1065       && $key != 'configure_errors'
1066       && $key != 'build_warnings'
1067       && $key != 'build_errors'
1068       && $key != 'test_errors'
1069       && $key != 'dynamicanalysis_errors')
1070      {
1071      continue;
1072      }
1073
1074    if($i>0)
1075      {
1076      $messagePlainText .= " and ";
1077      $titleerrors.=", ";
1078      }
1079
1080    switch($key)
1081      {
1082      case 'update_errors': $messagePlainText .= "update errors";$titleerrors.="u=".$value; break;
1083      case 'configure_errors': $messagePlainText .= "configure errors";$titleerrors.="c=".$value; break;
1084      case 'build_warnings': $messagePlainText .= "build warnings";$titleerrors.="w=".$value; break;
1085      case 'build_errors': $messagePlainText .= "build errors";$titleerrors.="b=".$value; break;
1086      case 'test_errors': $messagePlainText .= "failing tests";$titleerrors.="t=".$value; break;
1087      case 'dynamicanalysis_errors': $messagePlainText .= "failing dynamic analysis tests";$titleerrors.="d=".$value; break;
1088      }
1089    $i++;
1090    }
1091
1092  // Nothing to send we stop
1093  if($i==0)
1094    {
1095    return;
1096    }
1097
1098  // Title
1099  $titleerrors .= "):";
1100  $title = "FAILED ".$titleerrors." ".$Project->Name;
1101
1102  if($Build->GetSubProjectName())
1103    {
1104    $title .= "/".$Build->GetSubProjectName();
1105    }
1106  $title .= " - ".$Build->Name." - ".$Build->Type;
1107
1108  //$title = "CDash [".$project_array["name"]."] - ".$site_array["name"];
1109  //$title .= " - ".$buildname." - ".$buildtype." - ".date(FMT_DATETIMETZ,strtotime($starttime." UTC"));
1110
1111  $messagePlainText .= ".\n";
1112  $messagePlainText .= "You have been identified as one of the authors who ";
1113  $messagePlainText .= "have checked in changes that are part of this submission ";
1114  $messagePlainText .= "or you are listed in the default contact list.\n\n";
1115  $messagePlainText .= "Details on the submission can be found at ";
1116
1117  $messagePlainText .= $serverURI;
1118  $messagePlainText .= "/buildSummary.php?buildid=".$Build->Id;
1119  $messagePlainText .= "\n\n";
1120
1121  $messagePlainText .= "Project: ".$Project->Name."\n";
1122  if($Build->GetSubProjectName())
1123    {
1124    $messagePlainText .= "SubProject: ".$Build->GetSubProjectName()."\n";
1125    }
1126
1127  $Site  = new Site();
1128  $Site->Id = $Build->SiteId;
1129
1130  $messagePlainText .= "Site: ".$Site->GetName()."\n";
1131  $messagePlainText .= "Build Name: ".$Build->Name."\n";
1132  $messagePlainText .= "Build Time: ".date(FMT_DATETIMETZ,strtotime($Build->StartTime." UTC"))."\n";
1133  $messagePlainText .= "Type: ".$Build->Type."\n";
1134
1135  foreach($emailtext['category'] as $key=>$value)
1136    {
1137    switch($key)
1138      {
1139      case 'update_errors': $messagePlainText .= "Update errors: $value\n"; break;
1140      case 'configure_errors': $messagePlainText .= "Configure errors: $value\n"; break;
1141      case 'build_warnings': $messagePlainText .= "Warnings: $value\n"; break;
1142      case 'build_errors': $messagePlainText .= "Errors: $value\n"; break;
1143      case 'test_errors': $messagePlainText .= "Tests failing: $value\n"; break;
1144      case 'dynamicanalysis_errors': $messagePlainText .= "Dynamic analysis tests failing: $value\n"; break;
1145      }
1146    }
1147
1148  foreach($emailtext['summary'] as $summary)
1149    {
1150    $messagePlainText .= $summary;
1151    }
1152
1153  $serverName = $CDASH_SERVER_NAME;
1154  if(strlen($serverName) == 0)
1155    {
1156    $serverName = $_SERVER['SERVER_NAME'];
1157    }
1158  $messagePlainText .= "\n-CDash on ".$serverName."\n";
1159
1160  $sent = false;
1161
1162  // If this is the testing
1163  if($CDASH_TESTING_MODE)
1164    {
1165    add_log($emailaddress,"TESTING: EMAIL",LOG_TESTING);
1166    add_log($title,"TESTING: EMAILTITLE",LOG_TESTING);
1167    add_log($messagePlainText,"TESTING: EMAILBODY",LOG_TESTING);
1168    $sent = true;
1169    }
1170  else
1171    {
1172    // Send the email
1173    if(cdashmail("$emailaddress", $title, $messagePlainText,
1174     "From: CDash <".$CDASH_EMAIL_FROM.">\nReply-To: ".$CDASH_EMAIL_REPLY."\nContent-type: text/plain; charset=utf-8\nX-Mailer: PHP/" . phpversion()."\nMIME-Version: 1.0" ))
1175      {
1176      add_log("email sent to: ".$emailaddress." with errors ".$titleerrors." for build ".$Build->Id,"sendemail ".$Project->Name,LOG_INFO);
1177      $sent = true;
1178      }
1179    else
1180      {
1181      add_log("cannot send email to: ".$emailaddress,"sendemail ".$Project->Name,LOG_ERR);
1182      }
1183    } // end if testing
1184
1185  return $sent;
1186} // end send_email_to_address
1187
1188
1189function send_email_to_user($userid, $emailtext, $Build, $Project)
1190{
1191  require_once("models/user.php");
1192
1193  $User = new User();
1194  $User->Id = $userid;
1195  $email = $User->GetEmail();
1196
1197  $sent = send_email_to_address($email, $emailtext, $Build, $Project);
1198  if ($sent)
1199    {
1200    // Record that we have sent the email
1201    set_email_sent($userid, $Build->Id, $emailtext);
1202    }
1203
1204} // end send_email_to_user
1205
1206
1207function send_error_email($userid, $emailaddress, $sendEmail, $errors,
1208  $Build, $Project, $prefix = 'none')
1209{
1210  include("cdash/config.php");
1211  $emailtext = array();
1212  $emailtext['nerror'] = 0;
1213
1214  if ($userid != 0)
1215    {
1216    // For registered users, tune the error array based on user preferences
1217    // to make sure he doesn't get emails that are unwanted/unnecessary
1218    $UserProject = new UserProject();
1219    $UserProject->UserId = $userid;
1220    $UserProject->ProjectId = $Project->Id;
1221    $useremailcategory = $UserProject->GetEmailCategory();
1222    }
1223
1224  // Check if an email has been sent already for this user
1225  foreach($errors as $errorkey => $nerrors)
1226    {
1227    if($nerrors == 0 || $errorkey=='errors')
1228      {
1229      continue;
1230      }
1231
1232    $stop = false;
1233
1234    if($userid != 0)
1235      {
1236      // If the user doesn't want to get the email
1237      switch($errorkey)
1238        {
1239        case 'update_errors': if(!check_email_category("update",$useremailcategory)) {$stop=true;} break;
1240        case 'configure_errors': if(!check_email_category("configure",$useremailcategory)) {$stop=true;} break;
1241        case 'build_errors': if(!check_email_category("error",$useremailcategory)) {$stop=true;} break;
1242        case 'build_warnings': if(!check_email_category("warning",$useremailcategory)) {$stop=true;} break;
1243        case 'test_errors': if(!check_email_category("test",$useremailcategory)) {$stop=true;} break;
1244        case 'dynamicanalysis_errors': if(!check_email_category("dynamicanalysis",$useremailcategory)) {$stop=true;} break;
1245        }
1246      }
1247    else
1248      {
1249      // For committers, only send emails when the errorkey starts with the
1250      // prefix associated with the current handler calling us.
1251      // (So stop if the errorkey does not begin with the prefix...)
1252      // This minimizes sending out possibly near-duplicate emails to the
1253      // same committers...
1254      //
1255      if (0 !== strpos($errorkey, $prefix))
1256        {
1257        $stop = true;
1258        }
1259      }
1260
1261    if($stop)
1262      {
1263      continue;
1264      }
1265
1266    if(0 == $userid || !check_email_sent($userid, $Build->Id, $errorkey))
1267      {
1268      $emailtext['summary'][$errorkey] = get_email_summary($Build->Id,$errors,$errorkey,$Project->EmailMaxItems,
1269                                                           $Project->EmailMaxChars,$Project->TestTimeMaxStatus,
1270                                                           $Project->EmailTestTimingChanged);
1271      $emailtext['category'][$errorkey] = $nerrors;
1272      $emailtext['nerror'] = 1;
1273      }
1274    }
1275
1276  // Send the email
1277  if($emailtext['nerror'] == 1)
1278    {
1279    if($userid != 0)
1280      {
1281      send_email_to_user($userid, $emailtext, $Build, $Project);
1282
1283      if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/sendemail.php"))
1284        {
1285        $sendEmail->UserId = $userid;
1286        $sendEmail->Text = $emailtext;
1287        $sendEmail->SendToUser();
1288        }
1289      }
1290    else
1291      {
1292      send_email_to_address($emailaddress, $emailtext, $Build, $Project);
1293        //
1294        // Do we still need a "$sendEmail->" call here even if
1295        // there is no UserId...?
1296        //
1297      }
1298    }
1299}
1300
1301
1302function getHandlerErrorKeyPrefix($handler)
1303{
1304  if($handler instanceof UpdateHandler)
1305    {
1306    return "update_";
1307    }
1308
1309  if($handler instanceof TestingHandler)
1310    {
1311    return "test_";
1312    }
1313
1314  if($handler instanceof BuildHandler)
1315    {
1316    return "build_";
1317    }
1318
1319  if($handler instanceof ConfigureHandler)
1320    {
1321    return "configure_";
1322    }
1323
1324  if($handler instanceof DynamicAnalysisHandler)
1325    {
1326    return "dynamicanalysis_";
1327    }
1328
1329  return "none";
1330}
1331
1332/** function to send email to site maintainers when the update
1333  * step fails */
1334function send_update_email($handler,$projectid)
1335{
1336  include("cdash/config.php");
1337  include_once("cdash/common.php");
1338  require_once("cdash/pdo.php");
1339  require_once("models/build.php");
1340  require_once("models/project.php");
1341  require_once("models/buildgroup.php");
1342
1343  $Project = new Project();
1344  $Project->Id = $projectid;
1345  $Project->Fill();
1346
1347  // If we shouldn't sent any emails we stop
1348  if($Project->EmailBrokenSubmission == 0)
1349    {
1350    return;
1351    }
1352
1353  // If the handler has a buildid (it should), we use it
1354  if(isset($handler->BuildId) && $handler->BuildId>0)
1355    {
1356    $buildid = $handler->BuildId;
1357    }
1358  else
1359    {
1360    // Get the build id
1361    $name = $handler->getBuildName();
1362    $stamp = $handler->getBuildStamp();
1363    $sitename = $handler->getSiteName();
1364    $buildid = get_build_id($name,$stamp,$projectid,$sitename);
1365    }
1366
1367  if($buildid<0)
1368    {
1369    return;
1370    }
1371
1372  //  Check if the group as no email
1373  $Build = new Build();
1374  $Build->Id = $buildid;
1375  $groupid = $Build->GetGroup();
1376
1377  $BuildGroup = new BuildGroup();
1378  $BuildGroup->Id = $groupid;
1379
1380  // If we specified no email we stop here
1381  if($BuildGroup->GetSummaryEmail()==2)
1382    {
1383    return;
1384    }
1385
1386  // Send out update errors to site maintainers
1387  $update_errors = check_email_update_errors($buildid);
1388  if($update_errors['errors'])
1389    {
1390    // Find the site maintainer(s)
1391    $sitename = $handler->getSiteName();
1392    $siteid = $handler->getSiteId();
1393    $to_address = "";
1394    $email_addresses =
1395      pdo_query("SELECT email FROM ".qid("user").",site2user WHERE ".qid("user").".id=site2user.userid AND site2user.siteid='$siteid'");
1396    while($email_addresses_array = pdo_fetch_array($email_addresses))
1397      {
1398      if($to_address != "")
1399        {
1400        $to_address .= ", ";
1401        }
1402      $to_address .= $email_addresses_array["email"];
1403      }
1404
1405    if($to_address != "")
1406      {
1407      $serverURI = get_server_URI();
1408      // In the case of asynchronous submission, the serverURI contains /cdash
1409      // we need to remove it
1410      if($CDASH_BASE_URL=='' && $CDASH_ASYNCHRONOUS_SUBMISSION)
1411        {
1412        $serverURI = substr($serverURI,0,strrpos($serverURI,"/"));
1413        }
1414
1415      // Generate the email to send
1416      $subject = "CDash [".$Project->Name."] - Update Errors for ".$sitename;
1417
1418      $update_info = pdo_query("SELECT command,status FROM buildupdate AS u,build2update AS b2u
1419                              WHERE b2u.updateid=u.id AND b2u.buildid=".qnum($buildid));
1420      $update_array = pdo_fetch_array($update_info);
1421
1422      $body = "$sitename has encountered errors during the Update step and you have been identified as the maintainer of this site.\n\n";
1423      $body .= "*Update Errors*\n";
1424      $body .= "Status: ".$update_array["status"]." (".$serverURI."/viewUpdate.php?buildid=".$buildid.")\n";
1425
1426      $header =
1427        "From: CDash <".$CDASH_EMAIL_FROM.">\nReply-To: ".$CDASH_EMAIL_REPLY."\nContent-type: text/plain; charset=utf-8\nX-Mailer: PHP/" . phpversion()."\nMIME-Version: 1.0";
1428
1429      if($CDASH_TESTING_MODE)
1430        {
1431        add_log($to_address, "TESTING: EMAIL",LOG_TESTING);
1432        add_log($subject, "TESTING: EMAILTITLE",LOG_TESTING);
1433        add_log($body, "TESTING: EMAILBODY",LOG_TESTING);
1434        }
1435      else
1436        {
1437        if(cdashmail("$to_address", $subject, $body, $header))
1438          {
1439          add_log("email sent to: ".$to_address,"sendEmailExpectedBuilds");
1440          return;
1441          }
1442        else
1443          {
1444          add_log("cannot send email to: ".$to_address,"sendEmailExpectedBuilds");
1445          }
1446        }
1447      }
1448    }
1449}
1450
1451/** Main function to send email if necessary */
1452function sendemail($handler,$projectid)
1453{
1454  include("cdash/config.php");
1455  include_once("cdash/common.php");
1456  require_once("cdash/pdo.php");
1457  require_once("models/build.php");
1458  require_once("models/project.php");
1459  require_once("models/buildgroup.php");
1460
1461  $Project = new Project();
1462  $Project->Id = $projectid;
1463  $Project->Fill();
1464
1465  $sendEmail = NULL;
1466
1467  if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/sendemail.php"))
1468    {
1469    include_once("local/sendemail.php");
1470    $sendEmail = new SendEmail();
1471    $sendEmail->SetProjectId($projectid);
1472    }
1473
1474  // If we shouldn't sent any emails we stop
1475  if($Project->EmailBrokenSubmission == 0)
1476    {
1477    return;
1478    }
1479
1480  // If the handler has a buildid (it should), we use it
1481  if(isset($handler->BuildId) && $handler->BuildId>0)
1482    {
1483    $buildid = $handler->BuildId;
1484    }
1485  else
1486    {
1487    // Get the build id
1488    $name = $handler->getBuildName();
1489    $stamp = $handler->getBuildStamp();
1490    $sitename = $handler->getSiteName();
1491    $buildid = get_build_id($name,$stamp,$projectid,$sitename);
1492    }
1493
1494  if($buildid<0)
1495    {
1496    return;
1497    }
1498
1499  //add_log("Buildid ".$buildid,"sendemail ".$Project->Name,LOG_INFO);
1500
1501  //  Check if the group as no email
1502  $Build = new Build();
1503  $Build->Id = $buildid;
1504  $groupid = $Build->GetGroup();
1505
1506  $BuildGroup = new BuildGroup();
1507  $BuildGroup->Id = $groupid;
1508
1509  // If we specified no email we stop here
1510  if($BuildGroup->GetSummaryEmail()==2)
1511    {
1512    return;
1513    }
1514
1515  $emailCommitters = $BuildGroup->GetEmailCommitters();
1516
1517  $errors = check_email_errors($buildid,$Project->EmailTestTimingChanged,
1518                               $Project->TestTimeMaxStatus,!$Project->EmailRedundantFailures);
1519
1520  // We have some fixes
1521  if($errors['hasfixes'])
1522    {
1523    $Build->FillFromId($Build->Id);
1524    // Get the list of person who should get the email
1525    $lookup_result = lookup_emails_to_send($errors, $buildid, $projectid,
1526                                           $Build->Type, true, $emailCommitters);
1527    $userids = $lookup_result['userids'];
1528    foreach($userids as $userid)
1529      {
1530      $emailtext = array();
1531      $emailtext['nfixes'] = 0;
1532
1533      // Check if an email has been sent already for this user
1534      foreach($errors['fixes'] as $fixkey => $nfixes)
1535        {
1536        if($nfixes == 0)
1537          {
1538          continue;
1539          }
1540
1541        if(!check_email_sent($userid,$buildid,$fixkey))
1542          {
1543          $emailtext['category'][$fixkey] = $nfixes;
1544          $emailtext['nfixes'] = 1;
1545          }
1546        }
1547
1548      // Send the email
1549      if($emailtext['nfixes'] == 1)
1550        {
1551        send_email_fix_to_user($userid,$emailtext,$Build,$Project);
1552        }
1553      }
1554    }
1555
1556  // No error we return
1557  if(!$errors['errors'])
1558    {
1559    return;
1560    }
1561
1562  if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/sendemail.php"))
1563    {
1564    $sendEmail->BuildId = $Build->Id;
1565    $sendEmail->Errors = $errors;
1566    }
1567
1568  // If we should send a summary email
1569  if($BuildGroup->GetSummaryEmail()==1)
1570    {
1571    // Send the summary email
1572    sendsummaryemail($projectid,$groupid,$errors,$buildid);
1573
1574    if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/sendemail.php"))
1575      {
1576      $sendEmail->SendSummary();
1577      }
1578
1579    return;
1580    } // end summary email
1581
1582  $Build->FillFromId($Build->Id);
1583
1584  // Send build error
1585  if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/sendemail.php"))
1586    {
1587    $sendEmail->SendBuildError();
1588    }
1589
1590  // Lookup the list of people who should get the email, both registered
1591  // users *and* committers:
1592  //
1593  $lookup_result = lookup_emails_to_send($errors, $buildid, $projectid,
1594                                         $Build->Type, false, $emailCommitters);
1595
1596  // Loop through the *registered* users:
1597  //
1598  $userids = $lookup_result['userids'];
1599  foreach($userids as $userid)
1600    {
1601    send_error_email($userid, '', $sendEmail, $errors,
1602      $Build, $Project);
1603    }
1604
1605  // Loop through "other" users, if necessary:
1606  //
1607  // ...people who committed code, but are *not* registered CDash users, but
1608  // only if the 'emailcommitters' field is on for this build group.
1609  //
1610  if($emailCommitters)
1611    {
1612    $committeremails = $lookup_result['committeremails'];
1613    foreach($committeremails as $committeremail)
1614      {
1615      send_error_email(0, $committeremail, $sendEmail, $errors,
1616        $Build, $Project, getHandlerErrorKeyPrefix($handler));
1617      }
1618    }
1619}
1620?>
1621